如何使用前导零作为字符串读取/加载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没有在命令字典中存储为字符串'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
答案 0 :(得分:2)
首先,没有YAML字符串,没有集合(映射和序列)和标量。 假设这些标量未标记(如您的情况),则可以将它们标为引号(为简单起见,包括文字/折叠样式)或纯引号。
在正常情况下,加载YAML文档时,带引号的标量将作为字符串加载,并且 普通标量根据其“内容”开放为特殊类型的解释。那 解释可能导致它是布尔值,日期,浮点值。如果这些都不匹配,则将纯标量作为字符串加载。
正常加载情况适用Core Schema。该模式是一个 JSON模式的超集,并且在由 仅应将数字加载为integers。 因此,这回答了您有关如何处理“ YAML字符串”的第一个问题
ruamel.yaml,使用默认值(往返)
模式,如果您尝试保存YAML文档的特定格式,
加载,然后转储该文档(这并不总是可能的,但是
尝试)。尽管它以整数形式加载00005
,但实际上它是一个
整数类的子类型,其中包括有关格式的信息
整数(即包括前导零的数量)。如果你的
YAML文件受版本控制,这些事情很好
不要因为您更新了文档的其他部分而更改。
这应该回答您的第二个问题,询问ruamel.yaml为什么在输出中显示正确的标量。
PyYAML不会这样做(如果决定使用ruamel.yaml也不会这样做)
safe
正在加载)。而且您很幸运,您尝试过像00005
这样的标量
进行测试,因为00008
将作为字符串加载(因为PyYAML
使用2009年以前的YAML 1.1规范,其中前导零
表示八进制,在YAML 1.2中,八进制以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的作者。)
在默认的往返模式下,我加载
它们的行为类似于整数,但保留外部
特定于输入的外观,因为YAML提供了无尽的
表示任何特定数字(例如5
)的方式数量。
如果加载
完成yaml = YAML(typ='safe')
之后,您将获得
整数,不会以前导零转储。
如果在执行`yaml = YAML(typ ='base')之后加载,您将获得baseloader和每个 标量加载为字符串
作为程序:
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标量加载的结果字符串。替代 因为那样会从安全或往返模式中卸载整数匹配的正则表达式, 但这更复杂。