我刚刚开始使用YAML和Python,我试图在Python中解析包含锚点和别名的YAML。
在这个YAML中,我覆盖了锚点,使某些节点具有不同的值。
我的YAML的一个例子:
Some Colors: &some_colors
color_primary: &color_primary "#112233FF"
color_secondary: &color_secondary "#445566FF"
Element: &element
color: *color_primary
Overwrite some colors: &overwrite_colors
color_primary: &color_primary "#000000FF"
Another element: &another_element
color: *color_primary
具有(在JSON中)的预期结果:
{
"Some Colors": {
"color_primary": "#112233FF",
"color_secondary": "#445566FF"
},
"Element": {
"color": "#112233FF"
},
"Overwrite some colors": {
"color_primary": "#000000FF"
},
"Another element": {
"color": "#000000FF"
}
}
我测试了上面的YAML代码段here
从我在YAML文档中读到的内容;这应该可以从版本1.1(我认为),但至少YAML版本1.2应该支持它。
但是每当我尝试使用PyYAML(使用yaml.load()
)或ruamel,yaml
包(使用ruamel.yaml.load()
)解析YAML时,我都会收到“重复锚点”错误。
我在这里做错了什么?以及如何解决这个问题?
修改
在ruamel
的所有者的帮助下,我找到了上述问题的解决方案。
自ruamel
v0.12.3起,上述内容按预期工作,但您将收到ReusedAnchorWarning
。
可以使用以下代码段抑制这些警告:
import warnings
from ruamel.yaml.error import ReusedAnchorWarning
warnings.simplefilter("ignore", ReusedAnchorWarning)
给予应有的信用;所有这些都归ruamel
的所有者所有。
作为一个补充问题;当我将上述YAML修改为时(注意// <-- Added this
处的更改):
Some Colors: &some_colors
color_primary: &color_primary "#112233FF"
color_secondary: &color_secondary "#445566FF"
Element: &element
color: *color_primary
Overwrite some colors: &overwrite_colors
<<: *some_colors // <-- Added this to include 'color_secondary' as well
color_primary: &color_primary "#000000FF"
Another element: &another_element
color: *color_primary
输出结果为:
{
"Some Colors": {
"color_primary": "#000000FF",
"color_secondary": "#445566FF"
},
"Element": {
"color": "#112233FF"
},
"Overwrite some colors": {
"color_primary": "#000000FF",
"color_secondary": "#445566FF"
},
"Another element": {
"color": "#445566FF" // <-- Now the value is 'color_secondary' instead of 'color_primary'?
}
}
为什么color
的{{1}}会查看Another element
的值?
有没有办法解决这个问题?
答案 0 :(得分:2)
首先,你没有做错任何事。 PyYAML在这里做错了。这很可能是因为倾倒具有相同名称的锚点将是PyYAML转储器的错误情况。如果你有一个自我引用的Python结构:
a = dict(x=1)
a['y'] = a
然后PyYAML(和ruamel.yaml
)会为你创建一个唯一的锚名称。如果此名称不唯一,则取决于名称用作别名的位置。因此,怀疑任何重用的锚名称是有道理的,因为这可能指向YAML序列化代码中的错误,但它不符合规范(根据YAML 1.0规范重用已经没问题(3.2节)。 2.2))。
自2009年以来,python-yaml Debian模块的bug report存在,但我还没有发现它是否已经上传。
正如您所指出的,这在ruamel.yaml 0.12.3
中得到了解决要回答你的第二个问题,那只是因为&#34; Best Online YAML Converter&#34;不是,并解析这个错误。如果合并行上有YAML注释,它甚至会抛出错误:
<<: *some_colors # <-- Added this to include 'color_secondary' as well
这在ruamel.yaml(0.12.3)中按预期解析:
import sys
import ruamel.yaml
import warnings
from ruamel.yaml.error import ReusedAnchorWarning
warnings.simplefilter("ignore", ReusedAnchorWarning)
yaml_str = """\
Some Colors: &some_colors
color_primary: &color_primary "#112233FF"
color_secondary: &color_secondary "#445566FF"
Element: &element
color: *color_primary
Overwrite some colors: &overwrite_colors
<<: *some_colors # <-- Added this to include 'color_secondary' as well
color_primary: &color_primary "#000000FF"
Another element: &another_element
color: *color_primary
"""
data = ruamel.yaml.load(yaml_str)
ruamel.yaml.round_trip_dump(data, sys.stdout)
给出:
Some Colors:
color_primary: '#112233FF'
color_secondary: '#445566FF'
Overwrite some colors:
color_primary: '#000000FF'
color_secondary: '#445566FF'
Another element:
color: '#000000FF' # <- not #445566FF
Element:
color: '#112233FF'
(手动添加评论)
答案 1 :(得分:0)
仅供参考:缺少上面的示例代码pure=True
yaml = ruamel.yaml.YAML(typ='safe', pure=True)
data = yaml.load(yaml_str)
yaml.dump(data, sys.stdout)