如何强制PyYAML将字符串加载为unicode对象?
PyYAML这个包在加载没有标记的字符串时,会根据内容来决定是用unicode对象还是str对象。
我希望在我的程序中始终使用unicode对象(而且不幸的是,我现在还不能切换到Python 3)。
有没有简单的方法可以强制PyYAML总是将字符串加载为unicode对象?我不想在我的YAML文件里加上!!python/unicode
这样的标签。
# Encoding: UTF-8
import yaml
menu= u"""---
- spam
- eggs
- bacon
- crème brûlée
- spam
"""
print yaml.load(menu)
输出结果是:['spam', 'eggs', 'bacon', u'cr\xe8me br\xfbl\xe9e', 'spam']
我想要的是:[u'spam', u'eggs', u'bacon', u'cr\xe8me br\xfbl\xe9e', u'spam']
2 个回答
3
这里有一个函数,你可以用它来把从 PyYAML
解码出来的输出中的 str
类型替换成 unicode
类型:
def make_str_unicode(obj):
t = type(obj)
if t in (list, tuple):
if t == tuple:
# Convert to a list if a tuple to
# allow assigning to when copying
is_tuple = True
obj = list(obj)
else:
# Otherwise just do a quick slice copy
obj = obj[:]
is_tuple = False
# Copy each item recursively
for x in xrange(len(obj)):
obj[x] = make_str_unicode(obj[x])
if is_tuple:
# Convert back into a tuple again
obj = tuple(obj)
elif t == dict:
for k in obj:
if type(k) == str:
# Make dict keys unicode
k = unicode(k)
obj[k] = make_str_unicode(obj[k])
elif t == str:
# Convert strings to unicode objects
obj = unicode(obj)
return obj
print make_str_unicode({'blah': ['the', 'quick', u'brown', 124]})
29
这里有一个版本,它通过始终输出 unicode
来覆盖 PyYAML 对字符串的处理。实际上,这个结果可能和我之前发的另一个回答是一样的,只是更简短(也就是说,如果你使用自定义处理器,仍然需要确保自定义类中的字符串被转换成 unicode
,或者你自己传入 unicode
字符串):
# -*- coding: utf-8 -*-
import yaml
from yaml import Loader, SafeLoader
def construct_yaml_str(self, node):
# Override the default string handling function
# to always return unicode objects
return self.construct_scalar(node)
Loader.add_constructor(u'tag:yaml.org,2002:str', construct_yaml_str)
SafeLoader.add_constructor(u'tag:yaml.org,2002:str', construct_yaml_str)
print yaml.load(u"""---
- spam
- eggs
- bacon
- crème brûlée
- spam
""")
(上面的结果是 [u'spam', u'eggs', u'bacon', u'cr\xe8me br\xfbl\xe9e', u'spam']
)
我没有在 LibYAML
(基于 C 的解析器)上测试过,因为我无法编译它,所以我就不改动其他的回答了。