使用 PyYaml 加载特殊字符
Posted
技术标签:
【中文标题】使用 PyYaml 加载特殊字符【英文标题】:Loading special characters with PyYaml 【发布时间】:2017-12-06 02:56:03 【问题描述】:我正在努力在一个简单的 python 3.6 脚本中加载表情符号字符列表。 YAML 结构基本如下:
- ????
- ????
- ????
我的 python 脚本如下所示:
import yaml
f = open('emojis.yml')
EMOJIS = yaml.load(f)
f.close()
我收到以下异常:
yaml.reader.ReaderError: unacceptable character #x001d: special characters are not allowed in "emojis.yml", position 2
我已经看到了allow_unicode=True
选项,但这似乎只适用于 yaml.dump。似乎人们在 Python2 中遇到了类似问题,但由于所有字符串都应该是 unicode,我无法弄清楚为什么这不起作用。
我还尝试将我的表情符号用引号括起来,并为“tag:yaml.org,2002:str”使用客户构造函数。我的自定义构造函数可能从未被击中,因为 yaml lib 无法将我的表情符号识别为字符串类型。当我将表情符号直接定义为源代码中的字符串时,我也会观察到相同的行为。
有没有办法使用 PyYAML 加载包含表情符号的 yaml 文件?
【问题讨论】:
我认为 PyYAML 根本不支持 SMP。 @IgnacioVazquez-Abrams,对不起,没有 unicode 专家。 SMP,你的意思是补充多语言平面吗? SMP 是否定义了表情符号支持? @QuinnStearns SMP 是supplementary Unicode plane 1,该平面包括那些emoticons。 PyYAML 基于易于修改的测试考虑那些不可打印的。 PyYAML 的主要开发在 2010 年推出表情符号之前很久就停止了(即在 Unicode 6.0 及更高版本中),这也是 PyYAML 不支持最新的 YAML 1.2 标准(2009)的原因。一个简单的解决方法是重新定义可打印的 unicode 字符匹配规则。 【参考方案1】:您应该升级到 ruamel.yaml
(免责声明:我是该软件包的作者),它已修复此问题以及许多其他长期存在的 PyYAML 问题:
import sys
from ruamel.yaml import YAML
yaml = YAML()
with open('emojis.yml') as fp:
idx = 0
for c in fp.read():
print(':08x'.format(ord(c)), end=' ')
idx += 1
if idx % 4 == 0:
print()
with open('emojis.yml') as fp:
data = yaml.load(fp)
yaml.dump(data, sys.stdout)
给予:
0000002d 00000020 0001f642 0000000a
0000002d 00000020 0001f601 0000000a
0000002d 00000020 0001f62c 0000000a
['?', '?', '?']
如果你真的必须坚持使用 PyYAML,你可以这样做:
import yaml.reader
import re
yaml.reader.Reader.NON_PRINTABLE = re.compile(
u'[^\x09\x0A\x0D\x20-\x7E\x85\xA0-\uD7FF\uE000-\uFFFD\U00010000-\U0010FFFF]')
摆脱错误。
从版本 0.15.16 开始,ruamel.yaml
现在还转储所有补充平面 Unicode,而不恢复为 \Uxxxxxxxx
(可在新 API 中通过 .unicode_supplementary
控制,并取决于 allow_unicode
)。子>
【讨论】:
【参考方案2】:更新
最新版pyyaml已经修复了这个bug,升级到pyyaml>=5
原答案
这似乎是 pyyaml 中的一个错误,解决方法是使用它们的转义序列:
$ cat test.yaml
- "\U0001f642"
- "\U0001f601"
- "\U0001f62c"
$ python
...
>>> yaml.load(open('test.yaml'))
['?', '?', '?']
【讨论】:
啊啊啊太棒了!怎么没想到!?谢谢! 你并不总是可以控制 yaml 的内容,对吧?以上是关于使用 PyYaml 加载特殊字符的主要内容,如果未能解决你的问题,请参考以下文章