使用ruamel.yaml修改YAML会添加额外的新行 [英] Modifying YAML using ruamel.yaml adds extra new lines

查看:396
本文介绍了使用ruamel.yaml修改YAML会添加额外的新行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need to add an extra value to an existing key in a YAML file. Following is the code I'm using.

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之间没有空行时,就不会出现此问题.)

How can I get rid of the new line between b and c? (This problem is not there when phase1 is the only key in the file or when there are no blank lines between phase1 and phase2.)

推荐答案

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

The problem here is that the empty line is considered to be sort of a comment and that comments in ruamel.yaml are preserved by associating them with elements in a sequence or with keys in a mapping. That value is stored in a complex attribute named ca, on the list like object doc['phase1'], associated with the second element.

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

You can of course argue that it should be associated on the top level mapping/dict either associated with key phase1 (as some final empty-line-comment) or with phase2 as some introductory empty-line-comment. Either of the above three is valid and there is currently no control in the library over the strategy, where the empty line (or a comment goes).

如果您输入真实"注释(以#开头),则 将与phase1相关联作为结束注释,因为这些策略是不同的.

If you put in a "real" comment (one starting with #) it will be associated with phase1 as an end comment, for those the strategy is different.

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

This obviously needs an overhaul, as the original goal of ruamel.yaml was: - load some configuration from YAML - change some value - save the configuration to YAML in which case these kind of append/insert problems don't appear.

因此,只有在扩展库并对其附加(跟踪)注释和/或空行的位置进行一定控制之后,才有真正的解决方案.

So there is no real solution until the library is extended with some control over where to attach (trailing) comments and/or empty lines.

在实现这种控制之前,可能最好的操作如下:

Until such control gets implemented, probably the best thing you can do is the following:

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的值很小).

I changed the indent value to 4, which is what your input has (and get because you specify it as to small for the block_seq_indent).

这篇关于使用ruamel.yaml修改YAML会添加额外的新行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆