Дамп OrderedDict в более сжатом виде

У меня есть документ YAML в файле, который мне нужно обновить с помощью некоторой структурированной информации, которую я получаю из библиотеки. Порядок, в котором выгружаются ключи из этой информации, важен.

Файл YAML (input.yaml) выглядит так:

%YAML 1.1
---
- element 1  # this is the first element
- element 2

(пожалуйста, не спрашивайте, почему следующая программа в цепочке поддерживает только YAML 1.1, хотя версия 1.2 отсутствует уже более девяти лет)

Моя программа:

import sys
from collections import OrderedDict
from pathlib import Path
import ruamel.yaml

path = Path('input.yaml')

yaml = ruamel.yaml.YAML()  # defaults to round-trip
yaml.version = (1, 1)
yaml.explicit_start = True

data = yaml.load(path)

data.append(
    OrderedDict([
        ('hosts', 'all'), 
        ('vars', {'some_var': True}),
        ('tasks', [
            OrderedDict([('name', 'print some_var'), ('debug', {'var': 'some_var'})])
        ]),
    ]))


yaml.dump(data, sys.stdout)

с выходом:

%YAML 1.1
---
- element 1  # this is the first element
- element 2
- !!omap
  - hosts: all
  - vars:
      some_var: true
  - tasks:
    - !!omap
      - name: print some_var
      - debug:
          var: some_var

Как я могу вывести OrderedDicts без получения тегов !!omap и без ключа-значения в виде отдельных элементов в списке?

  • Я использую ruamel.yaml для сохранения существующих комментариев.
  • Я получаю эту структуру из библиотеки и не могу указать, что она должна использовать CommentedMap из ruamel.yaml.
  • Я знаю, как рекурсивно пройтись по структуре перед добавлением и преобразованием OrderedDict в CommentedMap ruamel.yaml, но это слишком медленно.

person Anthon    schedule 21.08.2018    source источник
comment
Впервые это сообщение было опубликовано неуместно как расплывчатый комментарий к проблеме в системе отслеживания проблем ruamel.yaml. Затем еще раз как столь же неясное и неуместное крупное предложение.   -  person Anthon    schedule 21.08.2018


Ответы (1)


Вы можете посмотреть, как CommentedMap регистрируется с RoundTripRepresenter, и использовать тот же код для своих OrderedDict. На самом деле вам нужна только одна дополнительная строка:

yaml.Representer.add_representer(OrderedDict, yaml.Representer.represent_dict)

при этом ваша программа дает вам:

%YAML 1.1
---
- element 1  # this is the first element
- element 2
- hosts: all
  vars:
    some_var: true
  tasks:
  - name: print some_var
    debug:
      var: some_var

Вы также можете использовать способ, которым PyYAML прикрепляет репрезентатор к совокупной структуре дампера:

ruamel.yaml.add_representer(OrderedDict, ruamel.yaml.RoundTripDumper.represent_dict, Dumper=ruamel.yaml.RoundTripDumper)

но это более подробно.

person Anthon    schedule 21.08.2018