PyYAML 不解析所有示例
PyYAML not parsing all examples
我试图理解 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 时如何"fix"。
但是示例 11 也失败了,它没有特殊标签并且是单个文档。 PyYAML 怎么能声称它可以解析所有示例,而它显然不能解析?这是因为 PyYAML 适用于 YAML 1.1 而示例来自 YAML 1.2 规范吗?
从你的最后一个问题开始:这是不是因为例子
来自后来的规范。假设你限制自己
规范中的预览 chapter/section(在线解析器也是如此),
考虑到我只比较了例子
视觉上(即不是基于字符的字符),示例
在 1.2 和 1.1 规范中 chapter/section 2 是相同的。
您的误解来自于在
在线解析器的标题。它实际上试图做的是 load
YAML,然后转储到 JSON、Python 或规范的 YAML。 正在加载
PyYAML 由 Processing 中提到的阶段组成
YAML 中的概述 图片
规范(1.1 和 1.2 相同),以字符为基础
文档:解析、组合和构建步骤。
PyYAML 不会在解析步骤上失败,但会在构造上失败
步骤,因为(如@torek 所示)PyYAML 构造了一个 list
和
不能用作 Python dict
的键。这是一个
Python 的 dict
实施和 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 可以 正确解析。不仅如此,如果在线"parser"
不会尝试加载,然后转储,当发出规范的 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 年代学过希腊字母表,所以我可以
阅读 (the) Greek (characters),但我不理解它们组成的单词。
在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]
我试图理解 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 时如何"fix"。
但是示例 11 也失败了,它没有特殊标签并且是单个文档。 PyYAML 怎么能声称它可以解析所有示例,而它显然不能解析?这是因为 PyYAML 适用于 YAML 1.1 而示例来自 YAML 1.2 规范吗?
从你的最后一个问题开始:这是不是因为例子 来自后来的规范。假设你限制自己 规范中的预览 chapter/section(在线解析器也是如此), 考虑到我只比较了例子 视觉上(即不是基于字符的字符),示例 在 1.2 和 1.1 规范中 chapter/section 2 是相同的。
您的误解来自于在 在线解析器的标题。它实际上试图做的是 load YAML,然后转储到 JSON、Python 或规范的 YAML。 正在加载 PyYAML 由 Processing 中提到的阶段组成 YAML 中的概述 图片 规范(1.1 和 1.2 相同),以字符为基础 文档:解析、组合和构建步骤。
PyYAML 不会在解析步骤上失败,但会在构造上失败
步骤,因为(如@torek 所示)PyYAML 构造了一个 list
和
不能用作 Python dict
的键。这是一个
Python 的 dict
实施和 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 可以 正确解析。不仅如此,如果在线"parser" 不会尝试加载,然后转储,当发出规范的 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 年代学过希腊字母表,所以我可以 阅读 (the) Greek (characters),但我不理解它们组成的单词。
在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]