通过ruamel保持YAML文件顺序

时间:2019-07-02 09:57:52

标签: python yaml ruamel.yaml

我正在尝试向YAML文件中添加新元素,但我希望这些新元素能够保持视觉秩序,使文件更易于人阅读。我勉强维持orderdict的顺序,但是有了这个,我们得到!! omap指令“污染” YAML文件。 我希望新元素具有相同的顺序,下面的代码中带有“ yaml_doc”示例。

有没有一种方法可以向YAML中添加新元素,并在转储文件而不显示omap指令时保持顺序?

下面是我拥有的代码和得到的输出:

import sys
from ruamel.yaml import YAML
from ruamel.yaml.comments import CommentedSeq as cs
from ruamel.yaml.comments import TaggedScalar as ts
from ruamel.yaml.scalarstring import SingleQuotedScalarString as sq
from ruamel.ordereddict import ordereddict


yaml_doc = """\
version: 0
projects:
  - name: A1
    dir: B1
    aplan:
      when: ["X", "Y", "Z"]
    wflow: l
"""
yaml = YAML()
yaml.preserve_quotes = True
yaml.width = 4096
data = yaml.load(yaml_doc)

ref = data['projects']

record_to_add = dict(name='A2', dir='B2',
                     aplan=dict(when=["X", "Y", "Z"]), wflow='l')
ref.append(record_to_add)

record_to_add_2 = ordereddict([('name', 'A3'), ('dir', 'B3'), ('aplan', ordereddict(
    [('when', ['X', 'Y', 'Z'])])), ('wflow', 'l')])
ref.append(record_to_add_2)

yaml.dump(data, sys.stdout)

转储的输出

version: 0
projects:
- name: A1
  dir: B1
  aplan:
    when: ["X", "Y", "Z"]
  wflow: l
- aplan:
    when:
    - X
    - Y
    - Z
  wflow: l
  name: A2
  dir: B2
- !!omap
  - name: A3
  - dir: B3
  - aplan: !!omap
    - when:
      - X
      - Y
      - Z
  - wflow: l

1 个答案:

答案 0 :(得分:1)

要保留键的顺序,ruamel.yaml使用ordereddict的子类, 您可以在加载后立即使用print(type(data))进行检查。那是CommentedMap 并且您应该像创建ordereddict一样创建它们:

import sys
from ruamel.yaml import YAML
from ruamel.yaml.comments import CommentedSeq as cs
from ruamel.yaml.comments import TaggedScalar as ts
from ruamel.yaml.scalarstring import SingleQuotedScalarString as sq
from ruamel.yaml.comments import CommentedMap as ordereddict


yaml_doc = """\
version: 0
projects:
  - name: A1
    dir: B1
    aplan:
      when: ["X", "Y", "Z"]
    wflow: l
"""
yaml = YAML()
yaml.preserve_quotes = True
yaml.width = 4096
data = yaml.load(yaml_doc)
# print(type(data['projects'][0])) # would give: <class 'ruamel.yaml.comments.CommentedMap'>

ref = data['projects']

record_to_add = dict(name='A2', dir='B2',
                     aplan=dict(when=["X", "Y", "Z"]), wflow='l')
ref.append(record_to_add)

record_to_add_2 = ordereddict([('name', 'A3'), ('dir', 'B3'), ('aplan', ordereddict(
    [('when', ['X', 'Y', 'Z'])])), ('wflow', 'l')])
ref.append(record_to_add_2)

yaml.dump(data, sys.stdout)

给出:

version: 0
projects:
- name: A1
  dir: B1
  aplan:
    when: ["X", "Y", "Z"]
  wflow: l
- name: A2
  dir: B2
  aplan:
    when:
    - X
    - Y
    - Z
  wflow: l
- name: A3
  dir: B3
  aplan:
    when:
    - X
    - Y
    - Z
  wflow: l

YAML spec中明确提到了有序的映射,这就是Python的orderdict在转储时映射的内容(在加载时是相反的)。 CommentedMap还可以处理保留的注释和节点属性。