Распарсить yaml файл в таблицу

На вход подается yaml файл:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: example
  namespace: Main
spec:
  selector:
    matchLabels:
      app: httpd
  replicas: 3
  template:
    metadata:
      labels:
        app: httpd
    spec:
      containers:
        - name: httpd
          image: >-
            image-registry.openshift-image-registry.svc:5000/openshift/httpd:latest
          ports:
            - containerPort: 8080

Нужно его превратить в таблицу, где первый столбец это ключ, а второй значение, причем ключ должен быть сохранен вместе с вложенностью.

Для начала я загружаю yaml файл:

import yaml
from yaml.loader import FullLoader
yaml_file_path = 'example/deployment.yaml'
with open(yaml_file_path) as file:
  data = yaml.load(file, Loader=FullLoader)
  print(data)

На монитор выводит файл полностью.

Теперь я хочу пройти весь файл и обработать каждый ключ, делаю рекурсивный метод:

def GetData(data):
  for item in data:
    print(item)
    GetData(item)

with open(yaml_file_path) as file:
  data = yaml.load(file, Loader=FullLoader)
  GetData(data)

Он уходит в бесконечную рекурсию и падает с ошибкой.

Помогите с решением, пожалуйста.


Ответы (1 шт):

Автор решения: CrazyElf

Ну вот вам пример рекурсивного обхода. У вас там кроме словарей есть ещё списки. Они хоть из одного элемента, но где гарантия, что не будет списков из нескольких элементов? Поэтому элементы списков я пронумеровал с нуля.

def GetData(data, prefix):
    if isinstance(data, dict):
        for k, v in data.items():
            yield from GetData(v, f'{prefix}/{k}')
    elif isinstance(data, list):
        for i, v in enumerate(data):
            yield from GetData(v, f'{prefix}/{i}')
    else:
        yield (prefix, data)

with open(yaml_file_path) as file:
    data = yaml.load(file, Loader=FullLoader)
    for item in GetData(data, ''):
        print(item)

На выходе кортежи, сами их приводите в какой нужно вид:

('/apiVersion', 'apps/v1')
('/kind', 'Deployment')
('/metadata/name', 'example')
('/metadata/namespace', 'Main')
('/spec/selector/matchLabels/app', 'httpd')
('/spec/replicas', 3)
('/spec/template/metadata/labels/app', 'httpd')
('/spec/template/spec/containers/0/name', 'httpd')
('/spec/template/spec/containers/0/image', 'image-registry.openshift-image-registry.svc:5000/openshift/httpd:latest')
('/spec/template/spec/containers/0/ports/0/containerPort', 8080)

P.S. А ваш код зацикливается, потому что он сначала перебирает ключи корневого словаря, потом сами эти ключи перебирает как коллекции - по одному символу, а потом каждый такой символ перебирает как коллекцию, ну и всё, дальше этот символ повторяется до бесконечности, потому что как коллекция он перебирается снова как этот же символ.

['apiVersion', 'kind', ...] -> ['a', 'p', 'i', ...] -> ['a'] -> ['a'] -> ...
→ Ссылка