有什么方法可以覆盖 pyyaml 对布尔值的自由处理吗?

Is there any way to override pyyaml's liberal handling of boolean values?

看起来 pyyaml 实现了 YAML 1.1 spec 的一部分,它允许将许多不同的值解释为真或假:

规范:

y|n

正则表达式:

y|Y|yes|Yes|YES|n|N|no|No|NO
 |true|True|TRUE|false|False|FALSE
 |on|On|ON|off|Off|OFF`

>>> for k in "y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF".split("|"):
...   print k, yaml.safe_load(k)
...
y y
Y Y
yes True
Yes True
YES True
n n
N N
no False
No False
NO False
true True
True True
TRUE True
false False
False False
FALSE False
on True
On True
ON True
off False
Off False
OFF False

但它会将它们序列化为 truefalse(与 YAML 1.1 的规范 yn 形成对比):

>>> yaml.safe_dump(dict(x=True, y=False))
'{x: true, y: false}\n'

是否有任何方法可以覆盖它,以便只有规范的 truefalse 值被解释为布尔值?

您应该执行以下操作以使 PyYAML 不将这些字符串识别为布尔值:

  • 替换在resolver.py中添加的隐式解析器,默认情况下为:

    Resolver.add_implicit_resolver(
            u'tag:yaml.org,2002:bool',
            re.compile(ur'''^(?:yes|Yes|YES|no|No|NO
                        |true|True|TRUE|false|False|FALSE
                        |on|On|ON|off|Off|OFF)$''', re.X),
            list(u'yYnNtTfFoO'))
    

    您将不得不跟踪 add_implicit_resolver 以查看它添加的位置,因为没有 remove_implicit_resolver。或者定义一个完整的新 ResolverBase subclass,它可以完成 Resolver 所做的一切,但没有如上所述的 2002:bool 定义,而是受限制的 (1.2) 版本.

  • 更新 constructor.pySafeConstructorbool_values class 属性

这并不能使 PyYAML 1.2 兼容,因为还有更多,PyYAML 并没有完全实现 YAML 1.1 规范。

将 YAML 加载到 python 并且不将 Yes 解释为布尔值的最简单方法是使用 ruamel.yaml 而不是 PyYAML(免责声明:我是该包的作者)。如果文件被标记为 YAML 1.1(如果没有标记 ruamel.yaml 假定版本 1.2),您还可以在其源代码中找到如何保持解析器 1.1 兼容。