我正在尝试使用 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 转储到多个文件中?
出现此问题主要是因为ruamel.yaml
开发 不要从您的注释#
comment
所属的数据结构开始(现在也没有)。它更容易的事实 向已创建的节点添加注释(即 在解析器遇到注释之前 YAML 文档)而不是添加它 到以下节点(在文档末尾可能不会显示 向上)。
在您的示例中,注释可能与键f
相关联,以 单元素序列的第一个元素,或第一个元素 的双项序列。ruamel.yaml
确实尝试进行一些重新排列,这已经 导致过去在与 两个连续的节点,这就是merge_comments
试图通过查找来解决的问题 这些评论是否相等。
这是一个权宜之计,但效果很好 如果您将ruamel.yaml
用于加载-修改-保存的预期目的,但 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__
列表和映射的表示形式,执行 保存注释、流、格式、定位点等信息的属性 不遵循文档中的建议:
如果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 将其解释为六条评论更为恰当。这 主要任务是定义拆分此类注释而不解释注释的含义,仅使用空行。
此外,节点分配可能会考虑注释的缩进级别。