用多行字符串读写yaml文件

用多行字符串读写yaml文件,yaml,multiline,pyyaml,Yaml,Multiline,Pyyaml,我必须读取一个yaml文件,修改它并使用pyYAML写回。除了在单引号中有多行字符串值(例如,如果输入yaml文件看起来像 FOO: - Bar: '{"HELLO": "WORLD"}' 然后将其读取为data=yaml.load(open(“foo.yaml”)并将其写入yaml.dump(data,fref,default\u flow\u style=False)生成如下内容 FOO: - Bar: '{"HELLO": "WORLD"}' i、 e.条值没有额外的行。奇怪的是,

我必须读取一个yaml文件,修改它并使用pyYAML写回。除了在单引号中有多行字符串值(例如,如果输入yaml文件看起来像

FOO:
  - Bar: '{"HELLO":
"WORLD"}'
然后将其读取为
data=yaml.load(open(“foo.yaml”)
并将其写入
yaml.dump(data,fref,default\u flow\u style=False)
生成如下内容

FOO:
- Bar: '{"HELLO": "WORLD"}'
i、 e.
值没有额外的行。奇怪的是,若输入文件有如下内容

FOO:
- Bar: '{"HELLO":

    "WORLD"}'

i、 e.为
值额外增加一行,然后将其写回生成正确数量的新行。你知道我做错了什么吗?

你没有做错什么,但是你可能应该读更多的YAML规范

根据PyYAML实现的(过时的)1.1规范,在 :

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

以及:

行折叠允许为了可读性而打断长行,同时保留单个长行的原始语义。折叠完成后,将保留以空行结尾的任何换行符。此外,即使在结束非空行时,也会保留任何特定的换行符

这意味着您的前两个示例与 换行符的读取就像有空格一样

第三个示例不同,因为加载后它实际上包含一个换行符,因为“保留以空行结尾的任何换行符”。 为了理解为什么它会在加载时转储回来,您必须知道PyYAML不会这样做 维护有关引用的任何信息(也不是第一个示例中的单个换行符),它 只需将该标量加载到Python字符串中。在转储期间,PyYAML计算该字符串 可以最好地编写和考虑选项(除非您尝试使用
default\u style
参数将内容强制为
dump()
):普通样式、单引号样式、双引号样式

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

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

FOO:
- Bar: |
  {"HELLO":
    "WORLD"}
但如果您加载,然后使用PyYAML转储它,那么它的可读性将丢失


虽然YAML 1.2规范(大约10年前发布)中的措辞不同,但折线的工作原理是相同的,因此这将“起作用”与最新的YAML加载器/转储程序类似。如果在
YAML()
实例上设置属性
preserve\u quotes=True
,则用于加载/转储YAML 1.2的我的包ruamel.YAML将正确地维护块样式,但在第一个示例中它仍将删除换行符。这是可以实现的(如ruamel.yaml所示,在折叠样式块标量中保留适当的换行符位置),但从来没有人要求这样做,可能是因为如果人们想要对包装进行这种控制,他们首先会使用块样式。

感谢@Anthon的详细解释。是的,我应该更详细地阅读规范。