如何使用ruamel.yaml自动添加引用?

时间:2017-05-04 09:56:01

标签: python yaml ruamel.yaml

前段时间我问了一个非常相似的question,但我仍然对如何在YAML转储上添加引用感到困惑。

我的目标是在默认值上添加锚点,以最大限度地减少转储上的冗余。所以我写了这个:

import collections
import ruamel.yaml as yaml

default = {'a': 1, 'b': 2, 'c': 3}

data = {
    (1,2,3,4): {1: {'a': 10}, 2: {'b': 20}},
    (5,6,7,8): {1: {}, 2: {'a': 100, 'b': 200, 'c': 300}},
}

d = yaml.comments.CommentedMap()
d.update(default)
d.yaml_set_anchor('default')
default = d

for m, a in data.items():
    for k in a.keys():
        u = yaml.comments.CommentedMap()
        u.update(a[k])
        u.add_yaml_merge([(0, default)])
        a[k] = u

data[None] = default

def my_key_repr(self, data):
    if isinstance(data, tuple):
        return self.represent_sequence(u'tag:yaml.org,2002:seq', data, flow_style=True)
    return yaml.representer.SafeRepresenter.represent_key(self, data)

yaml.representer.RoundTripRepresenter.represent_key = my_key_repr

print yaml.dump(data, Dumper=yaml.RoundTripDumper, width=100, allow_unicode=True,
                explicit_start=True)

预期输出为:

---
~: &default
  a: 1
  c: 3
  b: 2
[1, 2, 3, 4]:
  1:
    <<: *default
    a: 10
  2:
    <<: *default
    b: 20
[5, 6, 7, 8]:
  1:
    <<: *default
  2:
    <<: *default
    a: 100
    c: 300
    b: 200

我得到的是:

---
?
: &default
  a: 1
  c: 3
  b: 2
[1, 2, 3, 4]:
  1:
    <<: *default
    a: 10
  2:
    <<: *default
    b: 20
&id001 [5, 6, 7, 8]:
  1:
    <<: *id001
  2:
    <<: *id001
    a: 100
    c: 300
    b: 200

*id001来自无处......

1 个答案:

答案 0 :(得分:1)

这里有几个问题:

  • 如果您希望按键foobar显示在输出中,则必须在源代码中指定它们。

  • 如果您希望YAML文档是隐式的(即不是以---开头),那么您不应指定explicit_start=True

  • 无关键被转储为?而不是~

  • 如果您使用update()CommentedMap()填充dict(即有序字典),则无法期望按特定顺序添加密钥。如果您想按顺序acb(如您所示),您必须确保这是按照{{1} {1}}

  • 由于您的顶级CommentedMap()未订购,因此无法保证您的YAML文档中的顶层映射是data密钥(null? : )。

以下内容:

~:

准确地给出了您期望的输出。