问题 pyYAML字符串中“!”的错误


首先,免责声明:我对YAML不太熟悉。我正在尝试将YAML文档解析为关键值对(不要担心我是如何做的。我已经处理好了这一点)

我的文件过去看起来像:

world:
     people:
          name:Suzy
          address:chez-bob

然后,有人去改变它。

world:
     people:
          name:!$uzy
          address:chez-bob

我得到这个解析错误:

yaml.constructor.ConstructorError: could not determine a constructor for the tag '!$uzy'

这甚至意味着什么?我怎么会去解释它!$只有两个字符? 我只想要一个字符串键和值的字典! 此外,编辑yaml文件不是一个选项。必须使用解析器在代码中修复问题。


1863
2017-11-08 01:10


起源

所以是的,我现在意识到了!告诉它构造一个$ uzy,然而,文件的内容不是我关心的问题。以优雅的方式处理它是。我想要它做的是对待!$ uzy as text。 - Rokujolady
......还有,没有帮助。 - Rokujolady
用单引号或双引号括起来。 '!$ uzy'或“!$ uzy”。这将确保字符串被视为字符串。具有讽刺意味的是,我提出了这个问题,因为我需要做相反的事情 - 我需要构造函数。所以所有的努力都不会丢失。 - nelsonenzo


答案:


感叹号是YAML标记的前缀。解析器必须通过标记名称为它实现构造函数。有一些默认标签,如 !!bool!!int等,甚至一些Python特定的标签 !!python/tuple

您可以为前缀捕获的多个标记定义自己的构造函数甚至构造函数。通过定义前缀 '',你可以捕获所有标签并忽略它们。您可以从构造函数返回标记及其值,将其全部视为文本。

>>> import yaml
>>> def default_ctor(loader, tag_suffix, node):
...     print loader
...     print tag_suffix
...     print node
...     return tag_suffix + ' ' + node.value
...
>>> yaml.add_multi_constructor('', default_ctor)
>>> yaml.load(y)
<yaml.loader.Loader object at 0xb76ce8ec>
!$uzy
ScalarNode(tag=u'!$uzy', value=u'')
{'world': {'people': {'name': '!$uzy', 'address': 'chez-bob'}}}
>>>

11
2017-11-08 01:49



你能否提供一个更详细的例子,有类似的问题 这里 - askb
将前缀指定为 '' 不适合我,而是我必须把它设置为 '!'。 - dmitryb


如果值以“!”开头,则必须将值括在单引号或双引号中;否则它被解释为YAML标记。

world:
     people:
          name: "!$uzy"
          address: chez-bob

5
2017-11-08 04:24





这实际上是PyYAML中的一个错误。它解释了 : 在 name:!$uzy 作为键/值分隔符,但它只应该这样做 : 后跟一个空格,或者前面的标量(name)被引用。后续错误是应该在标量中间允许的感叹号被错误地解释为处于标量的开头并因此引入标记。

密钥的值 people 是字符串 name:!$uzy address:chez-bob 并在其他解析器(包括Python包)中正确处理 ruamel.yaml 其中我是作者)。


0
2018-03-14 12:20



看起来这个修复程序已经在2017年初的PyYAML资源中合并。但是自从上一个版本是2016年8月和2014年3月之前的版本以来,它可能需要几个月/几年才可以在PyPI上使用。 - Anthon