8

我正在使用 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' 进行硬引用,而无需在文件的其余部分强制使用这种引用样式?

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

4

2 回答 2

13

为了保留字符串标量的引号(和文字块样式),ruamel.yaml¹(在往返模式中)将这些标量表示为 SingleQuotedScalarString,DoubleQuotedScalarStringPreservedScalarString. 这些非常薄的包装器的类定义可以在scalarstring.py. 当序列化这些实例时,它们是“读取时”写入的,尽管有时当事情变得困难时表示器会回退到双引号,因为它可以表示任何字符串。

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

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创建(多余的)文档开始标记。顶级字典对象不“知道”这样的标记是否在原始文件中,因此您必须手动重新添加它。

请注意,如果没有preserve_quotes,值周围会有(单)引号,1并且2无论如何要确保它们被视为字符串标量而不是整数。


¹我是其中的作者。

于 2016-09-01T05:20:26.687 回答
5

从 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"))
于 2017-10-13T10:20:50.067 回答