Yaml end ("...") 总是被转储,即使 yaml.explicit_end=False

Yaml end ("...") always dumped even if yaml.explicit_end=False

我想知道这是否真的是错误或故意的,但无论如何。

为什么转储单个值总是包含明确的 YAML 结尾?

import sys
from ruamel.yaml import YAML
yaml=YAML()
yaml.explicit_end=False
yaml.dump(1, sys.stdout)

生产

1
...

能否以某种方式轻松跳过

我不确定原因,但 yaml.dump("1", sys.stdout) 没有打印文档的结束标记。

似乎序列化程序附加三个点 (document's end marker) 是在序列化程序获得 non-iterable 值时附加的:

dump(1, stream=sys.stdout)
dump([1], stream=sys.stdout)
dump(datetime.datetime.now(), stream=sys.stdout)
dump("1", stream=sys.stdout)

打印:

1
...
[1]
2019-07-09 12:45:27.013202
...
'1'

因此,一个简单的解决方法是在转储之前将您的值转换为字符串(如果可能)...

之所以添加 document-end-marker (...) 是因为 number 在根级别被转储为 plain 标量 文档。如果您转储字符串(假设该字符串 可以不用引号转储而不会被误解,即字符串 由数字组成,只需要被引用,以免被看到 作为整数)。

没有 document-end-marker,从流加载时,解析器 不知道文件是否完整,或者流是否正在等待填充。 document-end-marker 消除了这种歧义,所以这是有意的,但是例如在解析文件(而不是通用流)时,也可以并且将通过检查 end-of-file.

来完成

有几种解决方法,一种是转换输出:

import sys
import ruamel.yaml

def strip_document_end_marker(s):
   if s.endswith('...\n'):
       return s[:-4]

yaml = ruamel.yaml.YAML()
yaml.dump("abc", sys.stdout, transform=strip_document_end_marker)

给出:

abc

以上内容也适用于 dump_all 多个文档(最后一个是根级普通标量)。

实现此目的的另一种方法是在写入普通值后重置 open_ended 属性:

import sys
import ruamel.yaml

yaml = ruamel.yaml.YAML()

def wp(self, *args, **kw):
    self.write_plain_org(*args, **kw)
    self.open_ended = False

yaml.Emitter.write_plain_org = yaml.Emitter.write_plain
yaml.Emitter.write_plain = wp
yaml.dump("abc", sys.stdout)

这也给出了:

abc