У меня есть файл my_yaml.yml
со следующим содержимым:
my_yaml:
person: >
John|Doe|48,
Jack|Black|39
skills:
- name: superhero
abilities:
- swim
- run
special_chars:
- '! | " "'
- '+ | " "'
- '\ | " "'
- 'Á | "A"'
- 'É | "E"'
- 'Ű | "U"'
- 'Û | "U"'
Я хочу загрузить его, а затем сбрасывать в файл my_yaml_new.yml
имеющий полностью тот же формат и символы, что и исходный входной файл. Мой код:
import yaml
my_yaml = yaml.load(open('my_yaml.yml', encoding='utf8')) # without "utf8" encoding I get "'charmap' codec can't decode byte..." error
Я могу dump
его в консоль, но 1) порядок abilities
и name
изменился :(
yaml.dump(my_yaml, default_flow_style=False, allow_unicode=True)
Результат:
'my_yaml:\n person: >\n John|Doe|48, Jack|Black|39\n skills:\n - abilities:\n - swim\n - run\n name: superhero\n special_chars:\n - \'! | " "\'\n - + | " "\n - \\ | " "\n - Á | "A"\n - É | "E"\n - Ű | "U"\n - Û | "U"\n'
И когда я пытаюсь свалить файл:
with open('my_yaml_new.yml', 'w') as outfile:
yaml.dump(my_yaml, outfile, default_flow_style=False, allow_unicode=True)
2) Я получаю следующую ошибку из-за символа Û
:
UnicodeEncodeError: кодек 'charmap' не может кодировать символ '\ xdb' в позиции 0: символьные карты до неопределенных
Если я удалю эту строку из файла ввода my_yaml.yml
то выше дампа будет успешным, но 3) мои несколько строк в строке person
войдут в одну строку :(
my_yaml:
person: >
John|Doe|48, Jack|Black|39
skills:
- abilities:
- swim
- run
name: superhero
special_chars:
- '! | " "'
- + | " "
- \ | " "
- Á | "A"
- É | "E"
- Ű | "U"
4) А также мои одиночные кавычки (') исчезли из special_chars
:(
5) Также обратите внимание, что элементы skills
не имеют отступов :(
Я пробовал эти решения без успеха. И ни import ruamel.yaml as yaml
помог import ruamel.yaml as yaml
.
ОБНОВИТЬ
Хорошо, следующий отличный пакет решает проблемы 1) & 4), и я могу заменить >
на |
при многострочных значениях, так что 3) также решается. И, может быть, 5) не является большой проблемой. Но я все еще борюсь со специальными персонажами, такими как Û
или Ǘ
поэтому я все еще ищу решение проблемы 2)...
from ruamel import yaml
my_yaml = yaml.round_trip_load(open('dmy_yaml.yml', encoding='utf8'), preserve_quotes=True)
with open('my_yaml_new.yml', 'w') as outfile:
yaml.round_trip_dump(my_yaml, outfile, default_flow_style=False, allow_unicode=True)
Я не уверен, почему вы столкнулись с проблемами с unicode. Если у вас есть my_yaml.yml
и программа try.py
:
import sys
import ruamel.yaml
with open('my_yaml.yml') as fp:
yaml_str = fp.read().replace(': >\n', ': |\n')
yaml = ruamel.yaml.YAML()
yaml.indent(mapping=2, sequence=4, offset=2)
yaml.preserve_quotes = True
data = yaml.load(yaml_str)
new_file = 'my_yaml_new.yml'
with open(new_file, 'w') as ofp:
yaml.dump(data, ofp)
то это производит:
my_yaml:
person: |
John|Doe|48,
Jack|Black|39
skills:
- name: superhero
abilities:
- swim
- run
special_chars:
- '! | " "'
- '+ | " "'
- '\ | " "'
- 'Á | "A"'
- 'É | "E"'
- 'Ű | "U"'
- 'Û | "U"'
в virtualenv для Python2 и Python3 с ruamel.yaml 0.15.40.
Я использовал:
for n in 2 3 ; do mktmpenv -p /opt/python/$n/bin/python -qq -i ruamel.yaml; python --version; python try.py; deactivate; done
который, конечно, полагается на (последние) версии Python 2 и 3 для установки в /opt/python/2
resp. /opt/python/3
(которые они находятся в моей системе разработки Linux).
Обратите внимание, что Unicode не показывает проблем, что yaml.indent(mapping=2, sequence=4, offset=2)
сохраняет исходный отступ, но вам все равно нужно сменить сложенный многострочный скалярный на литеральный стиль (который я во время чтения в yaml_str
), поскольку ruamel.yaml не поддерживает сохранение этого (в первую очередь потому, что нет простого способа показать исходные точки складывания прозрачным способом).
encoding='utf-8
когда я читаю файл, пусть это будетpandas.read_csv()
или простоwith open()
. (sys.getdefaultencoding()
возвращается сutf-8
...)