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

标签 python yaml ruamel.yaml

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

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

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 不知从何而来...

最佳答案

这里有几个问题:

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

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

  • 为 None 的键将转储为 ? 而不是 ~

  • 如果您使用 update()dict 填充 CommentedMap() (即有序字典),您不能期望 key 按特定顺序添加。如果您希望按键按 acb 的顺序(如您所指示),则必须确保这是它们呈现给 CommentedMap()

  • 的顺序
  • 由于您的顶级 data 未排序,因此无法保证在您的 YAML 文档中顶级映射是 null 键 ( ? : ~:)。

以下内容:

from ruamel import yaml

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

abc = yaml.comments.CommentedMap()
abc['a'] = 100
abc['c'] = 300
abc['b'] = 200

base = [
    ('foo', {1: {'a': 10}, 2: {'b': 20}}),
    ('bar', {1: {}, 2: abc}),
]

data = yaml.comments.CommentedMap()
default = yaml.comments.CommentedMap()
for m, a in base:
    data[m] = a
for k in sorted(d):
    default[k] = d[k]
default.yaml_set_anchor('default')


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

data.insert(0, None, default)

x = yaml.round_trip_dump(data, width=100).replace('?\n:', '~:')
print(x)

给出了您期望的输出。

关于python - 如何使用 ruamel.yaml 自动添加引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43779615/

相关文章:

python - PyMQI for windows 构建和安装

python - Gspread 访问 google 电子表格 : HttpAccessTokenRefreshError, 无效的 JWT

python - 将数据类型声明为 ruamel.yaml 以便它可以表示/序列化它?

go - 我的 Go 服务器无法在 cloud foundry 中启动

deployment - 使用 GitLab CI 使发布分支的 DEPLOY 作业自动化,并为其他分支手动执行

python - 在 Python 中漂亮地将 2D 数组转储到 YAML

python - 使用 ruamel.yaml 检索文档头部的注释

python - 在 AWS Lambda 中访问 GET 参数

python - 运行时检查复杂变量参数

java - 如何在 Spring YAML 配置中转义 SpEL 美元符号?