Вывод YAML с Python: неправильное форматирование без списков при вводе - PullRequest
0 голосов
/ 06 февраля 2019

Я пытаюсь создать YAML из словарей Python.До сих пор я пробовал и PyYAML, и ruamel.yaml, и оба имеют одинаковый результат: если входной словарь не содержит списка, вывод не отформатирован правильно.

Вот скрипт:

from ruamel import yaml
import sys

yaml.dump({'name': 'Enterprise', 'class': 'Galaxy', 'armament': ['photon torpedoes','phasers'], 'number': 1701}, sys.stdout)
print('\n')
yaml.dump({'name': 'Enterprise', 'class': 'Galaxy', 'number': 1701}, sys.stdout)

А вот вывод:

armament: [photon torpedoes, phasers]
class: Galaxy
name: Enterprise
number: 1701

{class: Galaxy, name: Enterprise, number: 1701}

Требуемый вывод заключается в том, что второй дамп YAML должен быть отформатирован так же, как и первый.Что здесь происходит?

Ответы [ 2 ]

0 голосов
/ 06 февраля 2019

Вы используете API старого стиля, который по умолчанию выводит любые конечные узлы в стиле потока .В вашем случае и список / последовательность [photon torpedoes, phasers] и ваш дамп секунд (где корневой уровень равен конечному узлу).


Если предположить, что вам нужно не только объяснение, почему это происходит, но и то, как изменить это поведение, с новым API, используя экземпляры ruamel.yaml.YAML, по умолчанию все должно выполнятьсястиль, включающий все конечные узлы:

from ruamel.yaml import YAML
import sys

yaml = YAML()

yaml.dump({'name': 'Enterprise', 'class': 'Galaxy', 'armament': ['photon torpedoes','phasers'], 'number': 1701}, sys.stdout)
print()
yaml.dump({'name': 'Enterprise', 'class': 'Galaxy', 'number': 1701}, sys.stdout)

, дающий:

name: Enterprise
class: Galaxy
armament:
- photon torpedoes
- phasers
number: 1701

name: Enterprise
class: Galaxy
number: 1701

Все еще не то, что вы хотите: -)

Теперь у вас есть два варианта, чтобы получить то, чтовы указали: стиль потока конечных узлов в вашем первом дампе и стиль блоков конечных узлов в вашем втором.

Первый - это один экземпляр набора default_flow_style, используемый для первого дампа, и "нормальный"один для второго дампа:

from ruamel.yaml import YAML
import sys

yaml = YAML()

yaml.default_flow_style = None
yaml.dump({'name': 'Enterprise', 'class': 'Galaxy', 'armament': ['photon torpedoes','phasers'], 'number': 1701}, sys.stdout)
print()
yaml = YAML()
yaml.dump({'name': 'Enterprise', 'class': 'Galaxy', 'number': 1701}, sys.stdout)

, что дает:

name: Enterprise
class: Galaxy
armament: [photon torpedoes, phasers]
number: 1701

name: Enterprise
class: Galaxy
number: 1701

Второй вариант - явно установить стиль потока для объекта, который вы хотите вывести как последовательность.Для этого вам нужно создать экземпляр ruamel.yaml.comments.CommentedSeq, который обычно используется при загрузке для сохранения стиля потока / блока, комментариев и т. Д.:

from ruamel.yaml import YAML, comments
import sys

yaml = YAML()

armaments = comments.CommentedSeq(['photon torpedoes','phasers'])
armaments.fa.set_flow_style()
yaml.dump({'name': 'Enterprise', 'class': 'Galaxy', 'armament': armaments, 'number': 1701}, sys.stdout)
print()
yaml.dump({'name': 'Enterprise', 'class': 'Galaxy', 'number': 1701}, sys.stdout)

, который также дает:

name: Enterprise
class: Galaxy
armament: [photon torpedoes, phasers]
number: 1701

name: Enterprise
class: Galaxy
number: 1701

Этот второй вариант, конечно, дает вам прекрасный контроль (также есть CommentedMap), поскольку вы можете иметь эти объекты на всех уровнях иерархии данных, а не только на листьях, которые являются коллекциями.


Обратите внимание, что вам не нужно проходить ни одну из этих уловок при загрузке требуемого вывода из файла YAML, форматирование которого вы хотите.В этом случае диктат соотв.Экземпляры, подобные списку, создаются с правильным стилем потока / блока, поэтому выходные данные не изменяются неожиданно при простом изменении / добавлении значения и выгрузке обратно.

0 голосов
/ 06 февраля 2019

Это указано в документации о том, как сделать последовательный вывод:

yaml.dump({'name': 'Enterprise', 'class': 'Galaxy', 'number': 1701},
  sys.stdout,
  default_flow_style=False) # <- the important parameter

class: Galaxy
name: Enterprise
number: 1701
...