PyYAML 转储布尔值

Ano*_*ias 7 python jinja2 pyyaml

我正在从 YAML 文件加载 yaml True/False 项目(下面的示例)。

gzip: False
Run Code Online (Sandbox Code Playgroud)

这在 Jinja2 模板中被正确解释为布尔值 True。

另一个脚本正在读取同一个 YAML 文件,将其作为 python CGI 表单数据传递,并最终使用以下命令写入 YAML 文件

with open(myyaml, 'w') as yaml_file:
    yaml_file.write(yaml.dump(dict, default_flow_style=False)) 
Run Code Online (Sandbox Code Playgroud)

问题是,这会用单引号写入 True/False

gzip: 'False'
Run Code Online (Sandbox Code Playgroud)

这会导致 jinja2 模板不将值解释为布尔值,并且始终将值设置为 true

{{ if gzip }}
Run Code Online (Sandbox Code Playgroud)

有没有办法转储带有 True/False 值的 YAML 文件,这些值被视为布尔值(我的意思是不带引号)。

Ant*_*hon 4

.dump()只是转储它获取的数据,并且它必须获取字符串而不是布尔值作为 key 的值gzip。由于该字符串值如果不加引号转储可能会被误解为布尔值,因此它会被引用。

由于您从 CGI 获取材料,因此可以形成任何值TrueFalse字符串。在转储数据之前,您必须明确将从 CGI 获得的这些值转换为布尔值。

您可以先浏览一下字典并进行一些通用处理dump

import sys
import yaml

# simulating getting string type values from CGI
data = dict(gzip='False', intval="1", strval="abc") 

for k in data:
    v = data[k]
    try:
        v = int(v)
        data[k] = v
    except ValueError:
        vl = v.lower()
        if vl == 'false':
            data[k] = False
        elif vl == 'true':
            data[k] = True

yaml.safe_dump(data, sys.stdout, default_flow_style=False)
Run Code Online (Sandbox Code Playgroud)

给出:

gzip: false
intval: 1
strval: abc
Run Code Online (Sandbox Code Playgroud)

请注意,abc没有引号,因为它不能被解释为除了字符串之外的任何其他内容。当然,上面的内容也将字符串“True”或“False”转换为字符串。如果这不是您想要的,您必须根据密钥选择转换。

你的两行 Python 代码还有另外两个主要问题:

with open(myyaml, 'w') as yaml_file:
    yaml_file.write(yaml.dump(dict, default_flow_style=False)) 
Run Code Online (Sandbox Code Playgroud)
  1. 永远不应该使用 Python 关键字 ( dict) 作为变量名,这只会在以后的代码中自找麻烦。
  2. yaml.dump()将数据转储到流。它有一个功能,如果您不指定内容必须到达的流,则输出将写入内部流对象,并从中返回最终值。您不应该滥用这一点,然后将此返回值写入yaml_file. 相反,做:

    with open(myyaml, 'w') as yaml_file:
        yaml.dump(dict, yaml_file, default_flow_style=False))
    
    Run Code Online (Sandbox Code Playgroud)

    你的方式效率低下(除了表现出缺乏理解之外)。