使用 ruamel.yaml 修改 YAML 添加额外的新行
Modifying YAML using ruamel.yaml adds extra new lines
我需要向 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
是文件中唯一的键或 phase1
和 phase2
之间没有空行时,不会出现此问题。)
这里的问题是空行被认为是一种注释,ruamel.yaml
中的注释通过将它们与序列中的元素或映射中的键相关联来保留。该值存储在名为 ca
的复杂属性中,在列表中,如对象 doc['phase1']
,与第二个元素关联。
你当然可以争辩说它应该在顶层 mapping/dict 与键 phase1
相关联(作为一些最终的 empty-line-comment)或与 phase2
相关联作为一些介绍 empty-line-comment。
以上三个中的任何一个都是有效的,并且库中目前没有对策略的控制,其中空行(或注释)。
如果您输入 "real" 评论(以 #
开头),它 将 与 phase1
相关联作为结束评论,对于那些策略是不同的。
这显然需要大修,因为 ruamel.yaml
的最初目标是:
- 从 YAML 加载一些配置
- 改变一些价值
- 将配置保存到 YAML
在这种情况下,此类 append/insert 问题不会出现。
因此,在对库进行扩展并控制附加(尾随)注释的位置之前,没有真正的解决方案and/or 空行。
在实施此类控制之前,您最好做的可能是:
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 指定为较小值)。
我需要向 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
是文件中唯一的键或 phase1
和 phase2
之间没有空行时,不会出现此问题。)
这里的问题是空行被认为是一种注释,ruamel.yaml
中的注释通过将它们与序列中的元素或映射中的键相关联来保留。该值存储在名为 ca
的复杂属性中,在列表中,如对象 doc['phase1']
,与第二个元素关联。
你当然可以争辩说它应该在顶层 mapping/dict 与键 phase1
相关联(作为一些最终的 empty-line-comment)或与 phase2
相关联作为一些介绍 empty-line-comment。
以上三个中的任何一个都是有效的,并且库中目前没有对策略的控制,其中空行(或注释)。
如果您输入 "real" 评论(以 #
开头),它 将 与 phase1
相关联作为结束评论,对于那些策略是不同的。
这显然需要大修,因为 ruamel.yaml
的最初目标是:
- 从 YAML 加载一些配置
- 改变一些价值
- 将配置保存到 YAML
在这种情况下,此类 append/insert 问题不会出现。
因此,在对库进行扩展并控制附加(尾随)注释的位置之前,没有真正的解决方案and/or 空行。
在实施此类控制之前,您最好做的可能是:
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 指定为较小值)。