我有一个 .yml
文件,我正在尝试从中加载某些文档。我知道:
print yaml.load(open('doc_to_open.yml', 'r+'))
将打开 .yml
文件中的第一个(或唯一)文档,并且:
for x in yaml.load_all(open('doc_to_open.yml', 'r+')):
print x
这将打印文件中的所有 YAML 文档。但是假设我只想打开文件中的前三个文档,或者想打开文件中的第 8 个文档。我该怎么做?
最佳答案
如果您根本不想解析前七个 YAML 文件,例如出于效率原因,您必须自己搜索第 8 个文档。
可以挂接到解析器的第一阶段并计算流中 DocumentStartTokens()
的数量,并且仅在第 8 个之后开始传递 token 并停止这样做9 号,但这样做绝非易事。至少,这仍然会标记化所有前面的文档。
完全低效的方法(IMO)需要表现相同的有效替代方法,即在完成标记化/解析/后使用 .load_all()
并选择适当的文档/撰写/解决所有文档 ¹:
import sys
import ruamel.yaml
yaml = ruamel.yaml.YAML()
for idx, data in enumerate(yaml.load_all(open('input.yaml'):
if idx == 7:
yaml.dump(data, sys.stdout)
如果您在文档 input.yaml
上运行上述内容:
---
document: 0
---
document: 1
---
document: 2
---
document: 3
---
document: 4
---
document: 5
---
document: 6
---
document: 7 # < the 8th document
---
document: 8
---
document: 9
...
你得到输出:
document: 7 # < the 8th document
不幸的是,你不能天真地只计算文档 markers 的数量(---
),因为文档不必以 1 开头:
document: 0
---
document: 1
.
.
如果文件以 directive 开头,则第一行也不必有标记。 ²:
%YAML 1.2
---
document: 0
---
document: 1
.
.
或以仅包含注释的“文档”开头:
# the 8th document is the interesting one
---
document: 0
---
document: 1
.
.
考虑到您可以使用的所有内容:
def get_nth_yaml_doc(stream, doc_nr):
doc_idx = 0
data = []
for line in stream:
if line == u'---\n' or line.startswith('--- '):
doc_idx += 1
continue
if line == '...\n':
break
if doc_nr < doc_idx:
break
if line.startswith(u'%'):
continue
if doc_idx == 0: # no initial '---' YAML files don't start with
if line.lstrip().startswith('#'):
continue
doc_idx = 1
if doc_idx == doc_nr:
data.append(line)
return yaml.load(''.join(data))
with open("input.yaml") as fp:
data = get_nth_yaml_doc(fp, 8)
yaml.dump(data, sys.stdout)
并得到:
document: 7 # < the 8th document
在上述所有情况下,都非常高效,甚至不需要对前面的 YAML 文档(也不是下面的)进行标记。
还有一个额外的警告,YAML 文件可能以 byte-order-marker 开头。 ,并且 individual documents within a stream可以从这些标记开始。上面的例程不能处理这个问题。
<小时/>¹ 这是使用 ruamel.yaml 完成的我是其中的作者,它是 PyYAML 的增强版本。 AFAIK PyYAML 的工作方式相同(但例如会删除往返中的注释)。
² 从技术上讲,该指令有其自己的 directives document ,所以您应该将其算作文档,但 .load_all()
不会返回该文档,因此我不将其算作文档。
关于python - 从文件加载特定的 PyYAML 文档,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32493647/