如何在没有 YAML 指令的情况下加载 YAML 1.1 文件?

How to load a YAML 1.1 file without the YAML directive?

使用 ruamel.yaml v0.17.20,我正在尝试加载使用 PyYAML 生成的文件(或作者为仅使用 PyYAML 的软件编写的文件)。这些文件没有 YAML 指令,但 PyYAML 只支持 YAML 1.1,所以我需要以某种方式通知 ruamel.yaml 它应该使用 1.1 加载文件,即使没有指令。

from pathlib import Path
from ruamel.yaml import YAML

yaml = YAML()
yaml.version = (1, 1)
yaml.load(Path("some/path/to/file.yml"))  # file.yml exists and does not have a YAML directive

print(yaml.version)  # prints None
assert yaml.version == (1, 1)  # this fails!

当我尝试在没有 YAML 指令的情况下加载文件时,解析器会在 Parser.process_directives():

中用 None 覆盖我显式设置的 yaml.version
    def process_directives(self):
        # ...
        yaml_version = None
        # code that loads directives (but there aren't any in my case)

        if self.loader is not None and hasattr(self.loader, 'tags'):
            self.loader.version = yaml_version
            # ...

https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree/parser.py#l316

加载版本对于解析八进制和布尔值等事情很重要。

在解析缺少 YAML 指令的流时,如何告诉 ruamel.yaml 使用 1.1?

您的代码未指明加载 YAML 文档时发生的情况 没有 %YAML 指令,但你应该检查:

import sys
import ruamel.yaml

yaml_str = "- 042 # octal or not depending on YAML version"


print('# load as 1.1')
yaml = ruamel.yaml.YAML()
yaml.version = (1, 1)
data = yaml.load(yaml_str)
print(data[0])

print('# load as 1.2')  # the default no need to set the version
yaml = ruamel.yaml.YAML()
data = yaml.load(yaml_str)
print(data[0])

给出:

# load as 1.1
34
# load as 1.2
42

您应该能够使用 ruamel.yaml(在 round-trip 中)加载 YAML 1.1 并转储为 YAML 1.2。 您不能将 ruamel.yaml 用作 1.2 到 1.1 的转换器,往返 1.1 到 1.1 也不是 保证适用于所有文件。这些不是 ruamel.yaml

的预期用途

在 0.17 中,版本信息不附加到加载的数据,而是附加到 YAML() 实例 那会改变的。

或者设置版本,您可以在提交之前将适当的 header 添加到 bytes/str .load()

仅供参考:YAML 1.1 规范已在 12 年前被取代,PyYAML 中对 YAML 1.2 支持的 PR 于 2014 年推出。包含 YAML 文档的文件的推荐扩展名 自 2006 年以来一直 .yaml