使用PyYaml加载特殊字符

时间:2017-07-02 21:31:42

标签: python python-3.x unicode yaml python-3.6

我正在处理一个简单的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加载包含emojis的yaml文件?

2 个答案:

答案 0 :(得分:4)

你应升级到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(可通过.unicode_supplementary在新API中控制,并取决于{ {1}})。

答案 1 :(得分:3)

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

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

$ python
...
>>> yaml.load(open('test.yaml'))
['', '', '']