подуровни pyyaml ​​и yaml - PullRequest
       17

подуровни pyyaml ​​и yaml

1 голос
/ 19 октября 2019

Я пытаюсь использовать PyYAML для разбора файла YAML в объект python

Однако я сомневаюсь, что в ходе курса

У меня есть файл YAML

first_lvl:
   second_lvl:
       item_a:
          - value_a : "value aaa"
          - value_b : "value bbb"

Мой скрипт на python читает и загружает YAML в объект

import yaml

class Struct:
    def __init__(self, **entries):
        self.__dict__.update(entries)

with open(job_file.yml) as f:
    skeleton = yaml.full_load(f)

MyJob = Struct(**skeleton)

print(MyJob.first_lvl)

И это прекрасно работает, но только для первого уровня YAML. Как насчет того, чтобы я хотел получить значения подуровня файла yaml, которые, как предполагается, содержатся в объекте

следующим образом:

    print(MyJob.first_lvl.second_lvl) 

Возможно, он не связан с модулем PyYAMLвещь и многое другое, как Python обрабатывает объекты, но я все еще потерян

Может кто-нибудь пролить свет?

1 Ответ

0 голосов
/ 21 октября 2019

В ваших комментариях вы указываете, что предпочитаете загружать только один экземпляр Struct. Однако, если вы хотите получить доступ к значению "value aaa", написав my_job.first_lvl.second_lvl.item_a.0.value_a, вы не сможете сделать это, предоставив метод __getattr__, так как это приведет к ошибке, сообщающей, что объект dict не имеетатрибут second_lvl (он имеет только ключ second_lvl). __getattr__ никогда не вызывается, потому что в экземпляре Struct поиск атрибутов не завершается.

Что вы можете сделать, это предоставить некоторый метод lookup, который в качестве аргумента принимает "пунктирную" строку:

import ruamel.yaml

yaml_str = """\
first_lvl:
   second_lvl:
       item_a:
          - value_a : "value aaa"
          - value_b : "value bbb"
"""

class Struct:
    def __init__(self, **entries):
        self.__dict__.update(entries)

    def lookup(self, s):
        def recurse(d, names):
            name = names[0]
            if isinstance(d, list):  # list indices cannot be strings
                name = int(name)                
            if len(names) > 1:
                return recurse(d[name], names[1:])
            return d[name]

        names = s.split('.')
        return recurse(getattr(self, names[0]), names[1:])

yaml = ruamel.yaml.YAML(typ='safe')
my_job = Struct(**yaml.load(yaml_str))

print(my_job.lookup("first_lvl.second_lvl.item_a.0.value_a"))

, что дает:

value aaa

Этот ответ показывает альтернативное расширение структуры данных по умолчанию при использовании ruamel.yaml в режиме туда-обратно.

Если вы действительно хотите написать my_job.first_lvl.second_lvl.item_a.0.value_a без кавычек, я не думаю, что есть способ обойти каждый уровень осознанием поиска атрибутов. Это означает расширение Struct, так что класс может быть построен из сопоставления последовательностей и . Это можно сделать после загрузки YAML, но лучше всего выполнить IMO во время создания YAML.

...