使用ruamel.yaml修改YAML会添加额外的新行

时间:2017-02-11 04:58:45

标签: python yaml ruamel.yaml

我需要为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

如何摆脱bc之间的新界限? (当phase1是文件中的唯一键或phase1phase2之间没有空行时,此问题不存在。)

1 个答案:

答案 0 :(得分:0)

这里的问题是空行被认为是一种注释,ruamel.yaml中的注释通过将它们与序列中的元素或映射中的键相关联来保留。该值存储在名为ca的复杂属性中,类似于对象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的小值)。