我必须读取yaml文件,对其进行修改并使用pyYAML回写。一切正常,除非单引号中包含多行字符串值,例如,输入yaml文件看起来像
FOO:
- Bar: '{"HELLO":
"WORLD"}'
然后将其读取data=yaml.load(open("foo.yaml"))
并写入它会yaml.dump(data, fref, default_flow_style=False)
生成类似
FOO:
- Bar: '{"HELLO": "WORLD"}'
即没有多余的Bar
价值行。奇怪的是,如果输入文件具有类似
FOO:
- Bar: '{"HELLO":
"WORLD"}'
即,一条额外的新行用于Bar
价值,然后将其写回,将生成正确数量的新行。知道我在做什么错吗?
您没有做错任何事情,但是您可能应该阅读YAML规范的更多内容。
根据PyYAML在单引号标量内实现的(过时的)1.1规范:
在多行单引号标量中,换行符经受(流)行折叠,并且内容中排除任何尾随空白。
和折行:
行折叠允许将长行折断以提高可读性,同时保留单个长行的原始语义。折叠完成后,将保留以空行结尾的任何换行符。此外,即使结束非空行,也会保留任何特定的换行符。
这意味着您的前两个示例是相同的,因为读取换行符就好像有一个空格。
第三个示例有所不同,因为它实际上在装入之后包含换行符,因为“保留了以空行结尾的任何换行符”。为了理解为什么在加载时会回退,您必须知道PyYAML不会保留任何有关引用的信息(在第一个示例中也不包含单个换行符),它只是将标量加载到Python字符串中。在转储期间,PyYAML评估如何最好地编写该字符串以及它考虑的选项(除非您尝试使用的default_style
参数强制执行操作dump()
):纯样式,单引号样式,双引号样式。
PyYAML在可能的情况下将使用纯样式(不带引号),但是由于字符串以开头{
,因此与该字符用作流样式映射的开始时会造成混淆(冲突)。因此报价是必要的。由于字符串中也有双引号,并且没有需要反斜杠转义PyYAML可以选择的“最干净”表示的字符是单引号样式,并且在这种样式中,它需要通过包含空行来表示换行与单引号标量一起使用。
我个人更喜欢使用块样式文字标量来表示您的最后一个示例:
FOO:
- Bar: |
{"HELLO":
"WORLD"}
但是如果您加载,然后使用PyYAML转储该文件,则其可读性将丢失。
尽管在YAML 1.2规范(将近10年前发布)中措辞有所不同,但行折叠的作用相同,因此,对于更新的YAML加载程序/转储程序,它可以以类似的方式“工作”。如果您preserve_quotes = True
在YAML()
实例上设置属性,则用于加载/转储YAML 1.2的我的包ruamel.yaml会正确维护块样式,但是在您的第一个示例中,它仍然摆脱了换行符。可以实现这一点(如ruamel.yaml所示,在折叠样式块标量中保留适当的换行符位置),但从未有人提出过这样的要求,这可能是因为人们是否希望对包装进行这种控制,所以他们首先使用块样式。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句