我试图理解关于https://pyyaml.org/wiki/PyYAML的说法:

PyYAML features

- a complete YAML 1.1 parser. In particular, PyYAML can parse all
  examples from the specification.

如果转到使用PyYAML(http://yaml-online-parser.appspot.com/)的联机YAML解析器,则从规范中获取的几个示例将不起作用。
我知道您需要为其中一些失败定义标记,并且联机解析器只能处理单个文档YAML,我知道在使用PyYAML时如何“修复”。
但是示例11也失败了,它没有特殊的标记,是一个单独的文档。PyYAML怎么能声称它可以解析所有的示例,而它显然不能解析这些示例呢?这是因为PyYAML是针对YAML 1.1的,示例来自yaml1.2规范吗?

最佳答案

从你的最后一个问题开始:这不是因为例子
来自后来的规范。假设你把自己限制在
规范中的预览章节(与联机解析器一样),
考虑到我只比较了
在视觉上(即不是基于字符对字符的基础上),示例
在第2章/第2节的1.2和1.1规范中相同。
您的误解来自于在
联机分析器的标题。它实际上要做的是加载
然后转储到JSON、Python或规范的YAML。装载
PyYAML由YAML中ProcessingOverview图片中提到的阶段组成
规范(与1.1和1.2相同),从基于字符开始
文档:解析、合成和构造步骤。
PyYAML在解析步骤上没有失败,在构造过程中失败
步骤,因为(如@torek所示)PyYAML构造了一个list
不能用作Pythondict的键。这是一个
Pythondict实现的限制和IMO是PyYAML的不足之一。

import sys
import yaml as pyyaml

yaml_1_1_example_2_11 = """\
? - Detroit Tigers
  - Chicago cubs
:
  - 2001-07-23

? [ New York Yankees,
    Atlanta Braves ]
: [ 2001-07-02, 2001-08-12,
    2001-08-14 ]
"""

for event in pyyaml.parse(yaml_1_1_example_2_11):
    print(event)

给予:
StreamStartEvent()
DocumentStartEvent()
MappingStartEvent(anchor=None, tag=None, implicit=True)
SequenceStartEvent(anchor=None, tag=None, implicit=True)
ScalarEvent(anchor=None, tag=None, implicit=(True, False), value='Detroit Tigers')
ScalarEvent(anchor=None, tag=None, implicit=(True, False), value='Chicago cubs')
SequenceEndEvent()
SequenceStartEvent(anchor=None, tag=None, implicit=True)
ScalarEvent(anchor=None, tag=None, implicit=(True, False), value='2001-07-23')
SequenceEndEvent()
SequenceStartEvent(anchor=None, tag=None, implicit=True)
ScalarEvent(anchor=None, tag=None, implicit=(True, False), value='New York Yankees')
ScalarEvent(anchor=None, tag=None, implicit=(True, False), value='Atlanta Braves')
SequenceEndEvent()
SequenceStartEvent(anchor=None, tag=None, implicit=True)
ScalarEvent(anchor=None, tag=None, implicit=(True, False), value='2001-07-02')
ScalarEvent(anchor=None, tag=None, implicit=(True, False), value='2001-08-12')
ScalarEvent(anchor=None, tag=None, implicit=(True, False), value='2001-08-14')
SequenceEndEvent()
MappingEndEvent()
DocumentEndEvent()
StreamEndEvent()

所以PyYAML可以正确地解析这个。不仅如此,如果在线“解析器”
不会尝试加载,然后转储,当发出规范的YAML时,它可以
处理此示例(替换上面的最后两行
代码):
pyyaml.emit(pyyaml.parse(yaml_1_1_example_2_11), stream=sys.stdout, canonical=True)

因此:
---
{
  ? [
    ! "Detroit Tigers",
    ! "Chicago cubs",
  ]
  : [
    ! "2001-07-23",
  ],
  ? [
    ! "New York Yankees",
    ! "Atlanta Braves",
  ]
  : [
    ! "2001-07-02",
    ! "2001-08-12",
    ! "2001-08-14",
  ],
}

声明PyYAML解析所有示例,就像我声明我可以
读希腊语。我早在70年代就学会了希腊字母,所以我可以
读希腊语(字符),但我不懂它们构成的单词。
ruamel.yaml(免责声明:我是这个包的作者)中,您可以加载这个示例,甚至可以使用PyYAML
转储加载的数据。
from pprint import pprint
import ruamel.yaml
import yaml as pyyaml

yaml = ruamel.yaml.YAML(typ='safe')
data = yaml.load(yaml_1_1_example_2_11)
pprint(data)
print('*' * 50)
yaml.dump(data, sys.stdout)
print('*' * 50)
pyyaml.safe_dump(data, sys.stdout)

因此:
{('Detroit Tigers', 'Chicago cubs'): [datetime.date(2001, 7, 23)],
 ('New York Yankees', 'Atlanta Braves'): [datetime.date(2001, 7, 2),
                                          datetime.date(2001, 8, 12),
                                          datetime.date(2001, 8, 14)]}
**************************************************
? [Detroit Tigers, Chicago cubs]
: [2001-07-23]
? [New York Yankees, Atlanta Braves]
: [2001-07-02, 2001-08-12, 2001-08-14]
**************************************************
? [Detroit Tigers, Chicago cubs]
: [2001-07-23]
? [New York Yankees, Atlanta Braves]
: [2001-07-02, 2001-08-12, 2001-08-14]

关于python - PyYAML不解析所有示例,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53995421/

10-11 22:04