Загрузка специальных символов с помощью PyYaml
Я работаю над загрузкой списка символов emoji в простой python 3.6 script. Структура YAML состоит по существу следующим образом:
- 🙂
- 😁
- 😬
Мой python script выглядит следующим образом:
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, мне трудно понять, почему это не работает.
Я также попробовал обернуть свою emojis в кавычки и использовать конструктор клиента для "tag: yaml.org, 2002: str". Мой пользовательский конструктор никогда даже не попадает, по-видимому, из-за того, что yaml lib не распознает мой emoji как имеющий тип строки. Я также наблюдаю такое же поведение, когда я определяю свой emoji непосредственно как строку в источнике.
Есть ли способ загрузить файл yaml, содержащий emojis с PyYAML?
Ответы
Ответ 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 исправила эту ошибку, обновите до pyyaml>=5
Оригинальный ответ
Кажется, это ошибка в pyyaml, обходной путь - использовать их escape-последовательности:
$ cat test.yaml
- "\U0001f642"
- "\U0001f601"
- "\U0001f62c"
$ python
...
>>> yaml.load(open('test.yaml'))
['🙂', '😁', '😬']