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

Ale*_*vey 6 python ruamel.yaml

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

我有示例输入数据:

---
a: '1'
b: "2"
c: 3
Run Code Online (Sandbox Code Playgroud)

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

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

然后我编辑该数据:

data = read_file('in.yaml')
data['foo'] = 'bar'
Run Code Online (Sandbox Code Playgroud)

我使用以下方法写回磁盘:

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)
Run Code Online (Sandbox Code Playgroud)

输出文件是:

a: '1'
b: "2"
c: 3
foo: bar
Run Code Online (Sandbox Code Playgroud)

有没有一种方法可以强制引用字符串'bar',而不会在整个文件的其余部分强制执行引用样式?

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

Ant*_*hon 9

为了保留字符串标量报价(和文字块样式),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)
Run Code Online (Sandbox Code Playgroud)

得到:

---
a: '1'
b: "2"
c: 3
foo: 'bar'          # <- single quotes added
Run Code Online (Sandbox Code Playgroud)

所述yaml.explicit_start = True重新创建(多余)文件开始标记.顶级字典对象是否"知道"这样的标记是否在原始文件中,因此您必须手动重新添加它.

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


¹ 其中我是作者.


Ale*_*ing 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"))
Run Code Online (Sandbox Code Playgroud)