莫回无
你的标题让你看起来对正在发生的事情有点困惑,或者至少对术语有点困惑:虽然“YAML 数据结构”可能被解释为“从 YAML 文档加载的 Python 数据结构”的简写,但你没有进一步解析那个数据结构。任何解析都是作为 YAML 文档加载的一部分完成的,并且解析甚至在yaml.load() 返回之前就已完全完成。作为加载的结果,您在 Python 中有一个数据结构,您“只需要”通过递归遍历该数据结构来查找嵌套 Python 数据结构中的键。您的 YAML 示例有点无趣,因为它仅代表真实 YAML 的一小部分,因为您的 YAML 仅由作为字符串的(纯)标量、映射和作为标量的映射键组成。要遍历该数据结构,递归函数@aaaaaa 的简化版本将执行以下操作:import sysimport yamlyaml_str = """\all: children: allnetxsites: children: netxsites: hosts: bar.: ansible_ssh_host: bart.j domain: bart.local.domain nfs: lars.local.domain"""data = yaml.safe_load(yaml_str)def find(key, dictionary): # everything is a dict for k, v in dictionary.items(): if k == key: yield v elif isinstance(v, dict): for result in find(key, v): yield resultfor x in find("nfs", data): print(x)打印预期:lars.local.domain我已经简化了该功能,find因为代码段中版本中的列表处理 不正确。尽管使用的标量类型不会影响递归查找,但您可能需要一个更通用的解决方案,它可以处理带有(嵌套)序列、标记节点和复杂映射键的 YAML。假设您的输入文件稍微复杂一点input.yaml:all: {a: x}: !xyz - [k, l, 0943] children: allnetxsites: children: netxsites: hosts: bar.: ansible_ssh_host: bart.j domain: bart.local.domain nfs: lars.local.domain您可以使用ruamel.yaml(免责声明:我是该软件包的作者)来执行以下操作:import sysfrom pathlib import Pathimport ruamel.yamlin_file = Path('input.yaml')yaml = ruamel.yaml.YAML()data = yaml.load(in_file)def lookup(sk, d, path=[]): # lookup the values for key(s) sk return as list the tuple (path to the value, value) if isinstance(d, dict): for k, v in d.items(): if k == sk: yield (path + [k], v) for res in lookup(sk, v, path + [k]): yield res elif isinstance(d, list): for item in d: for res in lookup(sk, item, path + [item]): yield resfor path, value in lookup("nfs", data): print(path, '->', value)这使:['all', 'children', 'allnetxsites', 'children', 'netxsites', 'hosts', 'bar.', 'nfs'] -> lars.local.domain由于 PyYAML 仅解析 YAML 1.1 的一个子集并且加载的更少,因此它无法处理input.yaml.上面提到的片段,@aaaaa 正在使用的片段,由于(直接)嵌套的序列/列表,将在加载的 YAML 上中断