使用多行字符串读取和写回yaml文件

问题描述 投票:2回答:1

我必须读取yaml文件,修改它并使用pyYAML回写。除非单引号中有多行字符串值,否则每件事都可以正常工作,例如如果输入yaml文件看起来像

FOO:
  - Bar: '{"HELLO":
"WORLD"}'

然后读它作为qazxsw poi并写它qazxsw poi生成类似的东西

data=yaml.load(open("foo.yaml"))

即没有额外的yaml.dump(data, fref, default_flow_style=False)值。奇怪的是,如果输入文件有类似的东西

FOO:
- Bar: '{"HELLO": "WORLD"}'

即为Bar值增加一条新线,然后将其写回,生成正确数量的新线。知道我做错了什么吗?

yaml multiline pyyaml
1个回答
0
投票

你没有做错任何事,但你可能应该阅读更多的YAML规范。

根据PyYAML实现的(过时的)1.1规范,在FOO: - Bar: '{"HELLO": "WORLD"}' 中:

在多行单引号标量中,换行符受(流)行折叠,并且从内容中排除任何尾随空格。

Bar

线折叠允许打破长线以便于阅读,同时保留单条长线的原始语义。折叠完成后,将保留任何以空行结尾的换行符。此外,即使在结束非空行时,也会保留任何特定的换行符。

这意味着前两个示例是相同的,因为读取换行符就好像有空格一样。

第三个例子是不同的,因为它在加载后实际上包含一个换行符,因为“保留任何以空行结尾的换行符”。为了理解在加载时转储的原因,你必须知道PyYAML没有维护有关引用的任何信息(也没有关于第一个例子中的单个换行符),它只是将该标量加载到Python字符串中。在转储期间,PyYAML会评估如何最好地编写该字符串以及它所考虑的选项(除非您尝试使用single quoted scalars参数强制使用line-folding):简单样式,单引号样式,双引号样式。

PyYAML将尽可能使用普通样式(不带引号),但由于字符串以default_style开头,这会导致混淆(碰撞)该字符用作流样式映射的开始。因此引用是必要的。由于字符串中也有双引号,并且没有字符需要反斜杠转义PyYAML可以选择的“最干净”表示是单引号样式,并且在该样式中它需要通过包含emtpy行来表示换行符用单引号标量。

我个人更喜欢使用块样式文字标量来表示你的最后一个例子:

dump()

但如果你加载,然后使用PyYAML转储它的可读性将丢失。

尽管在YAML 1.2规范(近10年前发布)中措辞不同,但折线的工作方式相同,因此这将与更新的YAML装载器/倾卸器以类似的方式“工作”。我的包ruamel.yaml,用于加载/转储YAML 1.2将正确维护块样式,如果你在{实例上设置属性FOO: - Bar: | {"HELLO": "WORLD"} ,但它仍将摆脱你的第一个例子中的换行符。这可以实现(如ruamel.yaml在折叠样式块标量中保留适当的换行位置所示),但没有人曾经要求过,可能是因为如果人们想要对包装进行那种控制,他们会使用块样式开始。

© www.soinside.com 2019 - 2024. All rights reserved.