gpt4 book ai didi

python - 如何在Python中解析深度嵌套的yaml数据结构

转载 作者:行者123 更新时间:2023-12-01 01:03:16 25 4
gpt4 key购买 nike

我们有一个 YAML 文件,如下所示:

all:
children:
allnetxsites:
children:
netxsites:
hosts:
bar.:
ansible_ssh_host: bart.j
domain: bart.local.domain
nfs: lars.local.domain

我如何获取值 bar. 和键 nfs 的值?

Python 代码:

import yaml
with open("/Users/brendan_vandercar/sites.yaml", 'r') as stream:
data_loaded = yaml.load(stream)

for element in data_loaded:
name = "element"['all']['children']['allnetxsites']['children']['netxsites']['hosts']['bart']['nfs'][0]
print(name)

我想要得到的是该脚本的列表输出,其中包含以下内容:

Domain: bart.local.domain
NFS: lars.local.domain

最佳答案

你的标题让人觉得你对什么是有点困惑正在进行中,或者至少是关于术语:虽然“YAML 数据结构”可能被解释为“Python 数据结构”的简写从 YAML 文档加载”,您无需进一步解析该数据结构。任何解析都是作为 YAML 加载的一部分完成的文档和解析甚至在 yaml.load() 之前就已完全完成返回。加载后,您将获得一个 Python 数据结构,并且你“只”需要在嵌套的Python数据结构中查找键递归地遍历该数据结构。

<小时/>

您的 YAML 示例有点无趣,因为它仅代表真实 YAML 的一小部分,因为您的 YAML 仅由(普通)标量组成它们是字符串、映射和映射键,它们是标量。

为了遍历该数据结构,@aaaaaa 提出了递归函数的简化版本会做:

import sys
import yaml

yaml_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 result

for x in find("nfs", data):
print(x)

打印预期的内容:

lars.local.domain

我简化了函数find,因为版本中的列表处理 snippet不正确。

尽管使用的标量类型不影响递归查找,您可能需要一个更通用的解决方案来处理 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 sys
from pathlib import Path
import ruamel.yaml

in_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 res

for 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 中的有效 YAML。

上述代码片段,即 @aaaaa 正在使用的代码片段,将会中断由于(直接)嵌套序列/列表而加载的 YAML

关于python - 如何在Python中解析深度嵌套的yaml数据结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55601930/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com