使用PyYaml加载特殊字符

Qui*_*rns 12 python unicode yaml python-3.x python-3.6

我正在加载一个简单的python 3.6脚本中的表情符号字符列表.YAML结构基本如下:

-    
- 
- 
Run Code Online (Sandbox Code Playgroud)

我的python脚本如下所示:

import yaml
f = open('emojis.yml')
EMOJIS = yaml.load(f)
f.close()
Run Code Online (Sandbox Code Playgroud)

我收到以下异常:

yaml.reader.ReaderError: unacceptable character #x001d: special characters are not allowed in "emojis.yml", position 2
Run Code Online (Sandbox Code Playgroud)

我看过这个allow_unicode=True选项,但似乎只适用于yaml.dump.似乎人们在Python2中遇到了类似问题的麻烦,但由于所有字符串都应该是unicode,因此我无法弄清楚为什么这不起作用.

我也尝试用引号括起我的表情符号并使用客户构造函数来表示'tag:yaml.org,2002:str'.大概是因为yaml lib无法将我的表情符号识别为具有字符串类型,因此我的自定义构造函数永远不会被击中.当我将表情符号直接定义为源中的字符串时,我也会观察到相同的行为.

有没有办法用PyYAML加载包含表情符号的yaml文件?

Ant*_*hon 6

您应该升级到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)
Run Code Online (Sandbox Code Playgroud)

给出:

0000002d 00000020 0001f642 0000000a 
0000002d 00000020 0001f601 0000000a 
0000002d 00000020 0001f62c 0000000a 
['', '', '']
Run Code Online (Sandbox Code Playgroud)

如果您确实必须坚持使用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]')
Run Code Online (Sandbox Code Playgroud)

摆脱错误。


从0.15.16版本开始,ruamel.yaml现在还转储了所有补充平面Unicode,而不还原为\Uxxxxxxxx(可通过.unicode_supplementary,并取决于来在新API中控制allow_unicode)。


Ant*_*ile 5

更新资料

pyyaml的最新版本已修复此错误,请升级至 pyyaml>=5


原始答案

这似乎是pyyaml中的错误,一种解决方法是使用其转义序列:

$ cat test.yaml
- "\U0001f642"
- "\U0001f601"
- "\U0001f62c"

$ python
...
>>> yaml.load(open('test.yaml'))
['', '', '']
Run Code Online (Sandbox Code Playgroud)