python-3.x - PyYaml 将 '9:00' 解析为 int

标签 python-3.x yaml pyyaml

我有一个包含以下数据的文件:

classes:
  - 9:00
  - 10:20
  - 12:10

(以此类推至 21:00)

我使用 python3 和 yaml 模块来解析它。准确来说,来源是config = yaml.load (open (filename, 'r')) .但是,当我 print config ,我得到这部分数据的以下输出:
'classes': [540, 630, 730, 820, 910, 1000, 1090, 1180],

列表中的值是整数。

以前,当我使用 python2(和 BaseLoader 用于 YAML)时,我将值作为字符串获取,并按原样使用它们。 BaseLoader现在是 Not Acceptable ,因为我想从文件中读取 unicode 字符串,它给了我字节字符串。

那么,首先,为什么 pyyaml 将我的数据解析为整数?

其次,我如何防止 pyyaml 这样做?有可能吗不改变数据文件 (例如,不添加 !!str )?

最佳答案

YAML 的文档有点难以“解析”,所以我可以想象你错过了这个关于冒号的 little bit of info:

Normally, YAML insists the “:” mapping value indicator be separated from the value by white space. A benefit of this restriction is that the “:” character can be used inside plain scalars, as long as it is not followed by white space. This allows for unquoted URLs and timestamps. It is also a potential source for confusion as “a:1” is a plain scalar and not a key: value pair.



您在输入中的内容是 sexagesimal 并且您的 9:00 被认为类似于 9 分 0 秒,总共等于 540 秒。

不幸的是,这并没有被构造为一些特殊的 Sexagesimal 实例,可以像整数一样用于计算,但可以以其原始形式打印。因此,如果您想在内部将其用作字符串,则必须将它们单引号:
classes:
  - '9:00'
  - '10:20'
  - '12:10'

如果您转储 {'classes': ['9:00', '10:20', '12:10']}(并注意明确的 classes 没有得到任何引号),这就是您将得到的结果。
BaseLoader 为您提供字符串并不奇怪。 BaseConstructor 使用的 BaseLoader 任何 标量处理为字符串,包括整数、 bool 值和“你的”六十进制数:
import ruamel.yaml as yaml

yaml_str = """\
classes:
  - 12345
  - 10:20
  - abc
  - True
"""

data = yaml.load(yaml_str, Loader=yaml.BaseLoader)
print(data)
data = yaml.load(yaml_str, Loader=yaml.SafeLoader)

给出:
{u'classes': [u'12345', u'10:20', u'abc', u'True']}
{'classes': [12345, 620, 'abc', True]}

如果您真的不想使用引号,那么您必须“重置”以数字开头的标量的隐式解析器:
import ruamel.yaml as yaml
from ruamel.yaml.resolver import Resolver
import re

yaml_str = """\
classes:
  - 9:00
  - 10:20
  - 12:10
"""

for ch in list(u'-+0123456789'):
    del Resolver.yaml_implicit_resolvers[ch]
Resolver.add_implicit_resolver(
    u'tag:yaml.org,2002:int',
    re.compile(u'''^(?:[-+]?0b[0-1_]+
    |[-+]?0o?[0-7_]+
    |[-+]?(?:0|[1-9][0-9_]*)
    |[-+]?0x[0-9a-fA-F_]+)$''', re.X),  # <- copy from resolver.py without sexagesimal support
    list(u'-+0123456789'))

data = yaml.load(yaml_str, Loader=yaml.SafeLoader)
print(data)

给你:
{'classes': ['9:00', '10:20', '12:10']}

关于python-3.x - PyYaml 将 '9:00' 解析为 int,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23812676/

相关文章:

python - 正确地将变量传递给函数

python - 平等与同一性 - python

python-3.x - 使列表中的字符串大写 - Python 3

docker-compose,无法在docker容器中打印环境变量

kubernetes - Prometheus yaml 文件中的变量替换

python - FastAPI 是否支持具有嵌套结构(如 yaml)的配置文件?

python-3.x - Tkinter 单选按钮 : Remove dot along with image

.net-core - 'reportgenerator' 不是内部或外部命令,也不是可运行的程序或批处理文件

yaml - 在YAML中保留新行

django - django 理解 YML 吗? django 未加载固定装置 YML 文件(yml 不是已知的序列化)