我想知道是否有一种简单的方法可以使用 PyYAML 将由项目列表组成的 YAML 文档解析为 python 生成器。
例如,给定文件
# foobar.yaml
---
- foo: ["bar", "baz", "bah"]
something_else: blah
- bar: yet_another_thing
我希望能够做类似的事情
for item in yaml.load_as_generator(open('foobar.yaml')): # does not exist
print(str(item))
我知道有yaml.load_all,它可以实现类似的功能,但是你需要将每条记录视为自己的文档。我之所以问这个问题,是因为我有一些非常大的文件,我想将它们转换为 YAML,然后以低内存占用进行解析。
我查看了 PyYAML Events API,但它吓到了我 =)
最佳答案
我可以理解 Events API 让您感到害怕,而且它只能给您带来这么多。首先,您需要跟踪深度(因为您有顶级复杂序列项,以及“bar”、“baz”等。 而且,正确剪切低级序列事件元素后,您必须将它们输入到编写器中以创建节点(最终是 Python 对象),这也不是微不足道的。
但是由于 YAML 使用缩进,即使对于跨越多行的标量,您也可以使用一个简单的基于行的解析器,该解析器可以识别每个序列元素的起始位置,并将其馈送到正常的 load()
函数中一次:
#/usr/bin/env python
import ruamel.yaml
def list_elements(fp, depth=0):
buffer = None
in_header = True
list_element_match = ' ' * depth + '- '
for line in fp:
if line.startswith('---'):
in_header = False
continue
if in_header:
continue
if line.startswith(list_element_match):
if buffer is None:
buffer = line
continue
yield ruamel.yaml.load(buffer)[0]
buffer = line
continue
buffer += line
if buffer:
yield ruamel.yaml.load(buffer)[0]
with open("foobar.yaml") as fp:
for element in list_elements(fp):
print(str(element))
结果:
{'something_else': 'blah', 'foo': ['bar', 'baz', 'bah']}
{'bar': 'yet_another_thing'}
我使用了PyYAML的增强版,ruamel.yaml在这里(我是作者),但 PyYAML 应该以同样的方式工作。
关于python - YAML 列表 -> Python 生成器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29908931/