如果您必须处理具有多个不同标签的 YAML 文档,并且
只对其中的一部分感兴趣,你仍然应该
处理它们。如果您感兴趣的元素是嵌套的
在其他标记的构造中,您至少需要处理所有“封闭”标签
正确。
但是,您无需单独处理所有标签,您
可以编写一个可以处理映射、序列的构造函数例程
和标量注册到 PyYAML 的 SafeLoader 使用:
import yaml
inp = """\
MyEIP:
Type: !Join [ "::", [AWS, EC2, EIP] ]
Properties:
InstanceId: !Ref MyEC2Instance
"""
description = []
def any_constructor(loader, tag_suffix, node):
if isinstance(node, yaml.MappingNode):
return loader.construct_mapping(node)
if isinstance(node, yaml.SequenceNode):
return loader.construct_sequence(node)
return loader.construct_scalar(node)
yaml.add_multi_constructor('', any_constructor, Loader=yaml.SafeLoader)
data = yaml.safe_load(inp)
print(data)
给出:
{'MyEIP': {'Type': ['::', ['AWS', 'EC2', 'EIP']], 'Properties': {'InstanceId': 'MyEC2Instance'}}}
(inp也可以是打开读取的文件)。
如您在上面看到的,如果您的代码中出现意外的!Join 标签,它也将继续工作,
以及任何其他标签,如!Equal。标签刚刚被删除。
由于 YAML 中没有变量,所以有点猜测是什么
您的意思是“只喜欢解析描述变量”。如果有
显式标签(例如!Description),您可以通过添加 2-3 行来过滤掉这些值
到any_constructor,通过匹配tag_suffix参数。
if tag_suffix == u'!Description':
description.append(loader.construct_scalar(node))
然而,映射中的某些键更有可能是标量 description,
并且您对与该键关联的值感兴趣。
if isinstance(node, yaml.MappingNode):
d = loader.construct_mapping(node)
for k in d:
if k == 'description':
description.append(d[k])
return d
如果您知道数据层次结构中的确切位置,您可以
当然也走data结构并提取你需要的任何东西
基于键或列表位置。特别是在那种情况下,你会更好
使用我的ruamel.yaml,这是否可以在往返模式下加载标记的 YAML 而无需
额外的努力(假设上述inp):
from ruamel.yaml import YAML
with YAML() as yaml:
data = yaml.load(inp)