保留引号并在 Ruamel 中添加带引号的数据

Preserve quotes and also add data with quotes in Ruamel

我正在使用 Ruamel 来保留人工编辑的 YAML 文件中的引用样式。

我有示例输入数据:

---
a: '1'
b: "2"
c: 3

我使用以下方法读入数据:

def read_file(f):
    with open(f, 'r') as _f:
        return ruamel.yaml.round_trip_load(_f.read(), preserve_quotes=True)

然后我编辑该数据:

data = read_file('in.yaml')
data['foo'] = 'bar'

我写回磁盘使用:

def write_file(f, data):
    with open(f, 'w') as _f:
        _f.write(ruamel.yaml.dump(data, Dumper=ruamel.yaml.RoundTripDumper, width=1024))

write_file('out.yaml', data)

输出文件为:

a: '1'
b: "2"
c: 3
foo: bar

有没有一种方法可以强制对字符串 'bar' 进行硬引用,而无需在文件的其余部分强制执行该引用样式?

(另外,我可以阻止它删除三个破折号 --- 吗?)

为了保留字符串标量的引号(和文字块样式),ruamel.yaml¹——在往返模式中——将这些标量表示为 SingleQuotedScalarStringDoubleQuotedScalarStringPreservedScalarString。这些非常薄的包装器的 class 定义可以在 scalarstring.py 中找到。 当序列化这样的实例时,写成 "as they were read",尽管有时当事情变得困难时表示器会回退到双引号,因为它可以表示任何字符串。

要在添加新键值对(或更新现有键值对时)时获得此行为,您只需自己创建这些实例:

import sys
from ruamel.yaml import YAML
from ruamel.yaml.scalarstring import SingleQuotedScalarString, DoubleQuotedScalarString

yaml_str = """\
---
a: '1'
b: "2"
c: 3
"""

yaml = YAML()
yaml.preserve_quotes = True
yaml.explicit_start = True
data = yaml.load(yaml_str)
data['foo'] = SingleQuotedScalarString('bar')
data.yaml_add_eol_comment('# <- single quotes added', 'foo', column=20)
yaml.dump(data, sys.stdout)

给出:

---
a: '1'
b: "2"
c: 3
foo: 'bar'          # <- single quotes added

yaml.explicit_start = True 重新创建(多余的)文档开始标记。这样的标记是否存在于原始文件中是不是"known"顶级字典对象,所以你必须重新手动添加它。

请注意,如果没有 preserve_quotes,值 12 周围会有(单)引号,以确保它们被视为字符串标量而不是整数.


¹ 我是其中的作者。

从 Ruamel 0.15 开始,像这样设置 preserve_quotes 标志:

from ruamel.yaml import YAML
from pathlib import Path

yaml = YAML(typ='rt') # Round trip loading and dumping
yaml.preserve_quotes = True
data = yaml.load(Path("in.yaml"))
yaml.dump(data, Path("out.yaml"))