[英]How to automatically add a reference with ruamel.yaml?
I asked a very similar question some time ago, but I am still confused on how to add references on YAML dump. 不久前我问了一个非常类似的问题 ,但是我仍然对如何在YAML转储上添加引用感到困惑。
My goal is to add anchors on default values to minimize redundancy on my dump. 我的目标是在默认值上添加锚点,以最大程度地减少转储中的冗余。 So I wrote this: 所以我这样写:
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)
The expected output is: 预期的输出是:
---
~: &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
And what I get is: 我得到的是:
---
?
: &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
The *id001
comes from nowhere... *id001
来自任何地方...
There are several problems here: 这里有几个问题:
If you expect the keys foo
and bar
to show up in your output, you'll have to specify them in your source somewhere. 如果您期望键foo
和bar
出现在输出中,则必须在源代码中的某个地方指定它们。
If you expect your YAML document to be implicit (ie not starting with ---
), then you should not specify explicit_start=True
如果您希望自己的YAML文档是隐式的(即,不是以---
开头),则不应指定explicit_start=True
Keys that are None are dumped as ?
没有键被转储为?
not as ~
不如~
If you use update()
to fill a CommentedMap()
(ie a ordered dictionary) from a dict
, you cannot expect the keys to be added in a specific order. 如果使用update()
从dict
填充CommentedMap()
(即有序词典),则不能期望键会以特定顺序添加。 If you want the keys in order a
, c
, b
(as you indicate), you'll have to make sure that that is the order in which they are presented to the CommentedMap()
如果要按a
, c
, b
顺序(如您所指出的那样),则必须确保这是将它们呈现给CommentedMap()
的顺序。
Since your toplevel data
is not ordered, there is no guarantee that in your YAML document the toplevel mapping is the null
key ( ? :
or ~:
). 由于顶级data
未排序,因此不能保证在YAML文档中顶级映射为null
键( ? :
或~:
:)。
The following: 下列:
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)
gives exactly the output that you expected. 准确给出您期望的输出。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.