Разбор yaml в python, где верхний уровень не имеет определенного имени - PullRequest
0 голосов
/ 25 января 2020

У меня есть следующий файл 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 и использовать вложенные значения (хост, имя пользователя, пароль). Моя главная проблема заключается в том, что на верхнем уровне у меня нет только имени столбца значений (123, 345 в предоставленный пример)

Как я могу извлечь эту информацию из вышеупомянутого 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)

спасибо

Ответы [ 2 ]

2 голосов
/ 25 января 2020

Предполагая, что у каждого элемента в файле 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'}]

Однако вы можете обойтись, просто извлекая нужные значения при запуске для l oop:

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

Возможно, реальным ключевым моментом здесь является существование метода values в объектах dict.

1 голос
/ 25 января 2020

Вот еще одно средство, использующее простую рекурсивную функцию, которая будет выполнять поиск по ключевому слову:

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", []))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...