7

我需要为 YAML 文件中的现有键添加一个额外的值。以下是我正在使用的代码。

with open(yaml_in_path, 'r') as f:
    doc, ind, bsi = load_yaml_guess_indent(f, preserve_quotes=True)
doc['phase1'] += ['c']
with open(yaml_out_path, 'w') as f:
    ruamel.yaml.round_trip_dump(doc, f,
                                indent=2, block_seq_indent=bsi)

这是输入和输出。

输入

phase1:
  - a
  # a comment.
  - b

phase2:
  - d

输出

phase1:
  - a
  # a comment.
  - b

  - c
phase2:
  - d

我怎样才能摆脱和之间的新b线c?(当文件中的唯一键是唯一的键或和phase1之间没有空行时,此问题不存在。)phase1phase2

4

1 回答 1

2

这里的问题是空行被认为是一种注释,并且ruamel.yaml通过将它们与序列中的元素或映射中的键相关联来保留注释。该值存储在一个名为 的复杂属性中ca,在类似 object 的列表doc['phase1']中,与第二个元素相关联。

您当然可以争辩说它应该与顶级映射/字典相关联,或者与键相关联phase1(作为一些最终的空行评论)或phase2作为一些介绍性的空行评论。上述三个中的任何一个都是有效的,并且库中目前无法控制空行(或注释)所在的策略。

如果您输入“真实”评论(以 开头#),它将phase1结束评论相关联,因为策略不同。

这显然需要大修,因为最初的目标ruamel.yaml是: - 从 YAML 加载一些配置 - 更改一些值 - 将配置保存到 YAML,在这种情况下,不会出现此类附加/插入问题。

因此,在库被扩展并控制附加(尾随)注释和/或空行的位置之前,没有真正的解决方案。

在实施此类控制之前,您可以做的最好的事情可能是:

import sys
import ruamel.yaml

yaml_str = """\
phase1:
  - a
  # a comment.
  - b

phase2:
  - d
"""

def append_move_comment(l, e):
    i = len(l) - 1
    l.append(e)
    x = l.ca.items[i][0]  # the end comment
    if x is None:
        return
    l.ca.items[i][0] = None
    l.ca.items[i+1] = [x, None, None, None]

data = ruamel.yaml.round_trip_load(yaml_str)
append_move_comment(data['phase1'], 'c')
ruamel.yaml.round_trip_dump(data, sys.stdout, indent=4, block_seq_indent=2)

我将indent值更改为 4,这是您的输入所具有的(并得到,因为您将它指定为对于 block_seq_indent 而言很小)。

于 2017-02-11T08:34:48.733 回答