【问题标题】:PyYaml parses '9:00' as intPyYaml 将 '9:00' 解析为 int
【发布时间】:2014-05-22 16:40:38
【问题描述】:

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

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

(等到 21:00)

我使用 python3 和 yaml 模块来解析它。确切地说,来源是config = yaml.load (open (filename, 'r'))。但是,当我printconfig 时,我得到这部分数据的以下输出:

'classes': [540, 630, 730, 820, 910, 1000, 1090, 1180],

列表中的值是整数。

之前,当我使用 python2(以及用于 YAML 的 BaseLoader)时,我将值作为字符串获取,并按原样使用它们。 BaseLoader 现在不可接受,因为我想从文件中读取 unicode 字符串,它给了我字节字符串。

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

其次,我如何防止 pyyaml 这样做?是否可以不更改数据文件(例如不添加!!str)?

【问题讨论】:

    标签: python-3.x yaml pyyaml


    【解决方案1】:

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

    通常,YAML 坚持“:”映射值指示符与值之间用空格隔开。这个限制的一个好处是“:”字符可以在纯标量中使用,只要它后面没有空格。这允许不带引号的 URL 和时间戳。它也是一个潜在的混淆来源,因为“a:1”是一个普通的标量,而不是一个键:值对。

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

    不幸的是,它没有被构造为一些特殊的六十进制实例,可以像整数一样用于计算,但可以以其原始形式打印。因此,如果您想在内部将其用作字符串,则必须对它们进行单引号:

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

    如果你转储{'classes': ['9:00', '10:20', '12:10']},你会得到什么(并注意明确的classes 没有得到任何引号)。

    BaseLoader 为您提供字符串并不奇怪。 BaseLoader 使用的 BaseConstructorany 标量作为字符串处理,包括整数、布尔值和“你的”六十进制数:

    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']}
    

    【讨论】:

      【解决方案2】:

      你应该检查documentation of YAML

      冒号用于映射值。

      我想你想要一个字符串而不是一个整数,所以你应该用双引号括起来你的字符串。

      【讨论】:

      • 此链接已在我的浏览器中标记为已访问 :) 我应该更仔细地阅读它。虽然,现在在快速扫描 yaml 规范时,我没有找到我的具体案例。无论如何,谢谢你的解决方案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-12
      • 2018-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多