#python-3.x #dictionary #yaml #ruamel.yaml
Вопрос:
У меня есть этот образец YAML:
people:
name: abc
address: '55 Oxford Street, San Jose 95134. CA'
occupation: 'Travel Blogger'
Hobby: 'Travelling'
additional_interests: []
other_info: [['gender', 'male'], ['no_of_cars', 'three'],
['hair_color', 'black'], ['eye_color', 'brown']]
Который я хочу отобразить таким образом, чтобы выходной yaml был:
people:
name: abc
address: '55 Oxford Street, San Jose 95134. CA'
occupation: 'Travel Blogger'
Hobby: 'Travelling'
additional_interests: []
other_info: [
['gender', 'male'],
['no_of_cars', 'three'],
['hair_color', 'black'],
['eye_color', 'brown']
]
Я использую следующий код:
from ruamel.yaml import YAML as Ruamel
from pathlib import Path
yaml = Ruamel(typ='rt')
config_file = Path('/Users/test_config.yaml')
configs = yaml.load(config_file.read_text())
component_file="xyz.txt"
with open(component_file, 'w') as component:
for key, value in configs.items():
yaml.default_flow_style=None
yaml.dump({key: value}, component)
Идея здесь состоит в том, чтобы преобразовать существующие файлы YAML в более удобочитаемый формат. Любые указатели, как я могу получить формат, который я ищу — для вложенного списка в YAML?
Ответ №1:
Если используется, вам нужно установить только yaml.default_flow_style
один раз. но в режиме туда и обратно это влияет только на вновь созданные dict
s и list
s. Все загруженные структуры данных имеют свой стиль блока/потока, явно заданный и сохраненный, и на них это не влияет .default_flow_style
. Также почти всегда плохая идея-сбрасывать документ YAML с шагом в файл, таким образом вы можете легко создавать недопустимые/не загружаемые документы YAML.
Как задокументировано, ruamel.yaml
явно пытается сохранить стиль блока и, наоборот (в основном) нормализует стиль потока. Хороший тест, чтобы увидеть, сможете ли вы достичь того, чего хотите, в качестве вывода,-это обойти предполагаемый формат YAML, чтобы узнать, ruamel.yaml
может ли он повторно сгенерировать ваше форматирование (и если он проверяет узлы на предмет их специальных атрибутов, если вы хотите создать их с нуля).
В вашем случае вы заметите, что ruamel.yaml
он специально не обрабатывает эти списки в стиле вложенного потока и нормализует их в нежелательный формат образца.
Если бы между элементами вложенной последовательности были комментарии, вы бы заметили, что ruamel.yaml
в настоящее время не можете правильно с ними справиться. Они не теряются, но вставляются в отдельную строку, что является хорошим показателем того, что попытка вставить пустые комментарии между элементами внешней последовательности также приведет к появлению дополнительных новых строк.
Моя основная рекомендация — не вкладывать последовательности стилей потока.
import sys
import ruamel.yaml
yaml_str = """
people:
name: abc
address: '55 Oxford Street, San Jose 95134. CA'
occupation: 'Travel Blogger'
Hobby: 'Travelling'
additional_interests: []
other_info: [['gender', 'male'], ['no_of_cars', 'three'],
['hair_color', 'black'], ['eye_color', 'brown']]
"""
def no_nested_flow_style_seq(d):
done = False
if isinstance(d, dict):
for k, v in d.items():
no_nested_flow_style_seq(v) # you can have sequences as keys in YAML, but it is rare
elif isinstance(d, list):
for elem in d:
if not done and isinstance(elem, list):
done = True
d.fa.set_block_style()
no_nested_flow_style_seq(elem)
yaml = ruamel.yaml.YAML()
# yaml.preserve_quotes = True
data = yaml.load(yaml_str)
no_nested_flow_style_seq(data)
yaml.dump(data, sys.stdout)
что дает:
people:
name: abc
address: 55 Oxford Street, San Jose 95134. CA
occupation: Travel Blogger
Hobby: Travelling
additional_interests: []
other_info:
- [gender, male]
- [no_of_cars, three]
- [hair_color, black]
- [eye_color, brown]
Чтобы получить размер отступа в 6 пробелов для последовательностей сопоставления (в стиле блоков)
, как в вашем примере вывода, вы можете
установить yaml.indent(mapping=6, sequence=6, offset=4)
перед сбросом.
Однако, что касается. удобочитаемость для человека, есть статья «Отступы
и понятность программы» (1983, Миара, Муссельман, Наварро и Шнейдерман
(последний из известных диаграмм Насси-Шнейдермана).
в сообщениях ACM), что показывает, что понятность для языков программирования
оптимальна для отступов 2-4 пробелов и уменьшается при более высоких значениях.
Я не знаю о конкретных исследованиях для удобочитаемых форматов данных, и такие
вещи сильно зависят от того, к чему вы привыкли, и поэтому трудно
судить по личному опыту, но
Я рекомендую не использовать такие большие отступы для YAML.
Вышесказанное загружается в ту же структуру данных, что и оба ваших образца YAML (при любой нормальной обработке информация о форматировании, конечно, где-то хранится, но, безусловно, в других программах, не использующих ru).yaml в режиме туда и обратно не видит разницы).. Вы можете установить yaml.preserve_quotes = True
, но ИМО вам нужно будет разобраться с несоответствиями цитирования ( abc
vs 'Travelling'
), если люди будут просматривать эти файлы. Настройка, которая также загружает ту же структуру данных.
Если формат данных можно изменить, следует рассмотреть возможность изменения значения для other_info
на список диктов:
- gender: male
- no_of_cars: three
- hair_color: black
- eye_color: brown
или в список помеченных скаляров, который позволит вам загружать их в соответствующие экземпляры классов
(и, например, проверять допустимое скалярное значение):
- !Gender male
- !No_Of_Cars three
- !Hair_Color black
- !Eye_Color brown