如果你想创建类似的东西,至少在 ruamel.yaml 中,你应该使用往返模式,这也保留了合并。以下不会引发断言错误:
import ruamel.yaml
yaml_str = """\
foo: &xyz
a: 42
bar:
<<: *xyz
"""
data = ruamel.yaml.round_trip_load(yaml_str)
assert ruamel.yaml.round_trip_dump(data) == yaml_str
这意味着data
有足够的信息来重新创建输出中的合并。然而,在实践中,在往返模式下,永远不会发生合并。相反,检索一个值data['foo']['bar']['a']
意味着 中没有真正的键'bar'
,data['foo']
但随后会在附加的“合并映射”中查找该键。
这个没有公共接口(所以事情可能会改变),但是通过分析data
和查看ruamel.yaml.comments.CommentedMap()
你会发现有一个merge_attrib
(当前是 string _yaml_merge
)并且更有用的是有一个 method add_yaml_merge()
。后者采用 (int, CommentedMap()) 元组的列表。
baz = ruamel.yaml.comments.CommentedMap()
baz['b'] = 196
baz.yaml_set_anchor('klm')
data.insert(1, 'baz', baz)
您需要在数据'baz'
键之前插入键'bar'
,否则映射会反转。在合并中插入新结构后data['bar']
:
data['bar'].add_yaml_merge([(0, baz)])
ruamel.yaml.round_trip_dump(data, sys.stdout)
这使:
foo: &xyz
a: 42
baz: &klm
b: 196
bar:
<<: [*xyz, *klm]
(如果你想看看add_yaml_merge
插入了什么
print(getattr(data['bar'], ruamel.yaml.comments.merge_attrib))
通话前后)
如果你想完全从头开始,你可以这样做:
data = ruamel.yaml.comments.CommentedMap([
('foo', ruamel.yaml.comments.CommentedMap([('a', 42)])),
])
data['foo'].yaml_set_anchor('xyz')
data['bar'] = bar = ruamel.yaml.comments.CommentedMap()
bar.add_yaml_merge([(0, data['foo'])])
而不是data = ruamel.yaml.round_trip_load(yaml_str)
.
¹免责声明:我是该软件包的作者。