在python中解析yaml,其中上层没有明确的名称

2024-09-20 06:53:19 发布

您现在位置:Python中文网/ 问答频道 /正文

我有以下test.yaml文件

123:
  am: null
  cm:
    host: host1
    password: admin1234
    port: 443
    scheme: https
    username: admin
  dm:
    name: 123
    secret: abc
345:
  am: null
  cm:
    host: host2
    password: admin1234
    port: 443
    scheme: https
    username: admin
  dm:
    name: 123
    secret: abc

我有以下解析yaml文件的函数

import yaml
from typing import Optional, Dict, Any, cast


def read_yaml(path: str) -> Optional[Dict[str, Any]]:
    yaml_path = '{}/test.yaml'.format(path)
    with open(yaml_path, 'r') as res:
        try:
            yaml_parsed = cast(Dict[str, Any], yaml.safe_load(res))
        except yaml.YAMLError as e:
            logging.error(f"yaml parsing failed. Error: {e}")
            return None
        else:
            logging.info("yaml parsed succesfully.")
            return yaml_parsed

函数的调用和输出:

res = read_yaml(path)
print(res)
{123: {'am': None, 'cm': {'host': 'host1', 'password': 'admin1234', 'port': 443, 'scheme': 'https', 'username': 'admin'}, 'dm': {'name': 123, 'secret': 'abc'}}, 345: {'am': None, 'cm': {'host': 'host2', 'password': 'admin1234', 'port': 443, 'scheme': 'https', 'username': 'admin'}, 'dm': {'name': 123, 'secret': 'abc'}}}

我需要遍历这个yaml并使用嵌套值(主机、用户名、密码) 我的主要问题是,在顶层,我没有列名,只有值(在提供的示例中为123345)

如何从上述yaml中提取这些信息? 因此,我需要主机、用户名和密码这两个条目,这样我就可以迭代结果并使用这些值进行API调用

upd: 我需要这样的东西:(或者任何其他可以迭代和使用这些值的解决方案。如果我有一个列表列表,那么我可以解决这一部分,也许我可以使用原始格式,而无需任何转换,但我有限的python知识还不够)

[[host:host1 , username: admin, password: admin1234],[host:host2 , username: admin, password: admin1234]]

upd2: 在伪代码中需要类似的内容,并使用yaml中的值:

for i in mydict
    some_func(host,username,password)

谢谢


Tags: pathnamehttpshostyamlsecretadminport
2条回答

假设YAML文件中的每个项都有一个cm键,并且每个项都有您要查找的所有三个字段,这将把内容解压缩到您可以使用的字典列表中:

keys = ['host', 'username', 'password']
hosts = [{key: item['cm'][key] for key in keys} for item in res.values()]

hosts现在如下:

[{'host': 'host1', 'username': 'admin', 'password': 'admin1234'},
 {'host': 'host2', 'username': 'admin', 'password': 'admin1234'}]

但是,在运行for循环时,您可能只需要提取所需的值即可:

for item in res.values()
    cm = item['cm']
    some_func(cm['host'], cm['username'], cm['password'])

也许这里真正关键的洞察是dict对象中^{}方法的存在

下面是另一种方法,使用一个简单的递归函数,通过dict搜索关键字:

from typing import Dict
def deep_search_dico(that_dico, keyword, results):
    the_results = results.copy()
    for name, el in that_dico.items():
        if name == keyword:
            return el.copy()
        elif isinstance(el,dict):
            results.append(deep_search_dico(el, keyword, results))
    return results


the_dico = {123: {'am': None, 'cm': {'host': 'host1', 'password': 'admin1234', 'port': 443, 'scheme': 'https', 'username': 'admin'}, 'dm': {'name': 123, 'secret': 'abc'}}, 345: {'am': None, 'cm': {'host': 'host2', 'password': 'admin1234', 'port': 443, 'scheme': 'https', 'username': 'admin'}, 'dm': {'name': 123, 'secret': 'abc'}}}

print(deep_search_dico(the_dico, "cm", []))

相关问题 更多 >