如何以前导零作为字符串读取/加载YAML参数并在python 3.7中进行操作?从使用yaml-cpp(yaml 1.2)的C ++工具中,我得到一个包含leading_zero: 00005
的文本文件。读取/加载这行代码,似乎转换为int,但为什么呢?你知道如何用前导零处理YAML字符串吗?
import sys
from ruamel.yaml import YAML
yaml = YAML()
inp = "leading_zero: 00005\n"
code = yaml.load(inp)
print(code)
print(code['leading_zero'])
yaml.dump(code, sys.stdout)
ordereddict([('leading_zero', 5)])
5
leading_zero: 00005
正如您所看到的,00005未在ordereddict中存储为字符串'00005',但为什么yaml.dump()
显示正确的数字呢?
import yaml
inp = "leading_zero: 00005\n"
code = yaml.load(inp)
print(code)
print(yaml.dump(code, default_flow_style=False))
{'leading_zero': 5}
leading_zero: 5
首先,没有YAML字符串,有集合(映射和序列)和标量。假设这些标量没有标记(如你的情况),可以引用它们(为了简单起见,这包括文字/折叠样式)或简单。
在加载YAML文档的正常情况下,引用的标量将作为字符串加载,并且普通标量打开以作为特殊类型进行解释,具体取决于其“内容”。这种解释可能导致它是一个布尔值,一个日期,一个浮点值。如果这些都不匹配,则将普通标量加载为字符串。
正常的装载情况适用于Core Schema。该模式是JSON模式的超集,并且在由数字组成的两个普通标量中,只应加载为integers。所以这回答了关于如何处理“YAML字符串”的第一个问题
ruamel.yaml,使用默认(往返)模式,尝试在加载时保留YAML文档的特定格式,然后转储该文档(这并不总是可行,但它会尝试)。虽然它将00005
作为整数加载,但它实际上是整数类的子类型,其包括有关整数格式的信息(即包括前导零的数量)。如果您的YAML文档处于版本控制之下,那么这些事情不会因为您更新文档的其他部分而发生变化。
这应该回答你的第二个问题,问为什么ruamel.yaml在输出上显示正确的标量。
PyYAML不会这样做(如果决定使用safe
加载,ruamel.yaml也不会这样做)。而且你很幸运你为你的测试尝试了像00005
这样的标量,因为00008
将加载为一个字符串(因为PyYAML使用2009年之前的YAML 1.1规范,其中前导零表示八进制,在YAML 1.2 octals中以0o
开头)和00015
在ruamel.yaml中加载数字15
,在PyYAML中加载数字13:
import sys
import ruamel.yaml
import yaml as pyyaml
yaml_str = """\
- 00005
- 00008 # this is not an octal in YAML 1.1
- 00015
"""
yaml = ruamel.yaml.YAML()
data = yaml.load(yaml_str)
print('ruamel.yaml:', data, type(data[0]))
yaml.dump(data, sys.stdout)
print('-----------')
data = pyyaml.load(yaml_str)
print('pyyaml: ', data, type(data[0]))
pyyaml.dump(data, sys.stdout, default_flow_style=False)
这使:
ruamel.yaml: [5, 8, 15] <class 'ruamel.yaml.scalarint.ScalarInt'>
- 00005
- 00008 # this is not an octal in YAML 1.1
- 00015
-----------
pyyaml: [5, '00008', 13] <class 'int'>
- 5
- 00008
- 13
我是否知道如何使用前导零处理'“yaml字符串”,不,我不会,但我会根据您加载文档的目的给您几个选项供选择(只是为了清楚:我我是ruamel.yaml的作者。
5
。yaml = YAML(typ='safe')
后加载,你将只有普通的整数,不会使用前导零进行转储。作为一个程序:
from ruamel.yaml import YAML
for t in ['rt', 'safe', 'base']: # 'rt' is the default
data = YAML(typ=t).load("00005")
dt = type(data)
print(f'{t:5} {data!r:7} {dt}')
得到:
rt 5 <class 'ruamel.yaml.scalarint.ScalarInt'>
safe 5 <class 'int'>
base '00005' <class 'str'>
因此,如果您不喜欢往返模式的魔术“整数”,请使用基本模式加载并自行处理从YAML标量加载的结果字符串。另一种方法是从安全或往返模式卸载整数匹配正则表达式,但这更复杂。