我正在尝试使用ruamel.yaml将以下yaml文件转储到多个(不同的)文件中:
C:
f:
# comment
- - l1
- l2: '5'
如果我尝试执行deepcopy
,则注释会导致深度复制版本的错误:
import copy
from ruamel.yaml import YAML
yaml = YAML()
conf = None
with open("input.yaml", 'r') as inf:
conf = yaml.load(inf)
conf2 = copy.deepcopy(conf)
with open("out1.yaml", 'w') as outf:
yaml.dump(conf, outf)
try:
with open("out2.yaml", 'w') as outf:
yaml.dump(conf2, outf)
print("all good")
except AssertionError:
raise SystemExit("Deep copy failed")
是否有一种方法可以将带有此类注释的已加载YAML转储到多个文件中?
答案 0 :(得分:2)
主要是由于ruamel.yaml
开发
不是从注释#
comment
所属的数据结构的规范开始(现在也没有)。更容易的事实
向已创建的节点添加评论(即
解析器遇到注释之前的YAML文档)而不是添加它
到下一个节点(在文档末尾可能不会显示)
上)。
在您的示例中,注释可以与键f
关联,以
单元素序列的第一个元素,或到第一个元素
双重项目顺序的ruamel.yaml
确实尝试进行一些重新排列,
导致过去的一次评论与
两个连续的节点,这就是merge_comments
试图通过观察来解决
这些评论是否相等。
这是一个权宜之计,但效果很好
如果您将ruamel.yaml
用于其预期的load-modify-save用途,则使用Deepcopy
不保留此引用,从而导致不平等,因此AssertionError
快速而肮脏的解决方案是使merge_comments
成为无操作人员:
import copy
from ruamel.yaml import YAML
yaml = YAML()
conf = None
with open("input.yaml", 'r') as inf:
conf = yaml.load(inf)
conf2 = copy.deepcopy(conf)
with open("out1.yaml", 'w') as outf:
yaml.dump(conf, outf)
yaml.representer.merge_comments = lambda x, y: None
try:
with open("out2.yaml", 'w') as outf:
yaml.dump(conf2, outf)
print("all good")
except AssertionError:
raise SystemExit("Deep copy failed")
给出:
all good
带有out1.yaml
的内容:
C:
f:
# comment
- - l1
- l2: '5'
和out2.yaml
中的
C:
f:
# comment
- - l1
- l2: '5'
此问题被“增强”为__deepcopy__
列表和映射的表示形式,对
包含注释,流,格式,锚点等信息的属性
不遵循the documentation中的建议:
如果 deepcopy ()实现需要对文件进行深拷贝 组件,则应使用该组件调用deepcopy()函数 作为第一个参数,备注字典作为第二个参数。
但是改变并不能解决问题,而是一种更具结构性的解决方案
将对注释将要应用的内容有明确的定义,并且
取消merge_comments
。那应该
包括如下拆分多行注释:
# this documents has some non-trivial
# comment lines
# first item follows
- 42
# end of first item
# second item follows
- 196
# end of second item
# final comment of the document
当前,以上内容将加载三个(多行)注释,但是IMO 最好将其解释为六个评论。的 主要任务是仅使用空行来拆分这些注释,而不解释注释的含义。
另外,在节点分配中也可以考虑注释的缩进级别。