Преобразование файла YAML в python dict

У меня возникает следующая проблема: сопоставление документов в файле YAML с dict и их правильное отображение.

У меня есть следующий файл YAML, который представляет собой сервер (db.yml):

instanceId: i-aaaaaaaa
     environment:us-east
     serverId:someServer
     awsHostname:ip-someip
     serverName:somewebsite.com
     ipAddr:192.168.0.1
     roles:[webserver,php]

Я загружаю этот файл YAML, который я могу сделать без каких-либо проблем. Думаю, я это понимаю.

instanceId = getInstanceId()
stream = file('db.yml', 'r')
dict = yaml.load_all(stream)

for key in dict:
    if key in dict == "instanceId":
        print key, dict[key]

Я бы хотел, чтобы логика работала следующим образом:

  • загрузить yaml, map to dict
  • посмотрите в каждом dict в документе, если instanceId соответствует тому, что было установлено getInstanceId(), затем распечатайте все ключи и значения для этого документа.

Если я посмотрю на структуру данных карты из командной строки, я получаю:

{'instanceId': 'i-aaaaaaaa environment:us-east serverId:someServer awsHostname:ip-someip serverName:someserver ipAddr:192.168.0.1 roles:[webserver,php]'}

Я думаю, что я мог бы неправильно создать структуру данных для файла YAML, а при совпадении содержимого с dict я немного потерял.

Боковое примечание: я не могу загрузить все документы в этом файле с помощью yaml.load(), я пробовал yaml.load_all(), который, похоже, работает, но моя основная проблема все еще существует.

Ответ 1

Я думаю, что ваш файл yaml должен выглядеть (или, по крайней мере, что-то вроде этого, поэтому он все равно структурирован):

instance:
     Id: i-aaaaaaaa
     environment: us-east
     serverId: someServer
     awsHostname: ip-someip
     serverName: somewebsite.com
     ipAddr: 192.168.0.1
     roles: [webserver,php]

Затем yaml.load(...) возвращает:

{'instance': {'environment': 'us-east', 'roles': ['webserver', 'php'], 'awsHostname': 'ip-someip', 'serverName': 'somewebsite.com', 'ipAddr': '192.168.0.1', 'serverId': 'someServer', 'Id': 'i-aaaaaaaa'}}

И вы можете идти оттуда...


Используется так:

>>> for key, value in yaml.load(open('test.txt'))['instance'].iteritems():
    print key, value


environment us-east
roles ['webserver', 'php']
awsHostname ip-someip
serverName somewebsite.com
ipAddr 192.168.0.1
serverId someServer
Id i-aaaaaaaa

Ответ 2

Дополнительная ошибка в коде, которая не связана с YAML:

for key in dict:
    if key in dict == "instanceId": # This doesn't do what you want
        print key, dict[key]

in - это оператор, который работает в типах последовательностей, а также на картах. Вот почему это не синтаксическая ошибка... но она не делает то, что вы хотите.

key in dict всегда будет оцениваться до True, потому что все ключи, которые вы выполняете, находятся в dict. Таким образом, ваш код сводится к True == "instanceId", который всегда будет оцениваться как False, потому что логическое значение True никогда не будет равно этой строке.

Возможно, вы заметили, что оператор print не производит никакого вывода; это потому, что он никогда не вызывается.

Ответ 3

Просто используйте python-benedict, это подкласс dict, который обеспечивает поддержку ввода/вывода для большинства распространенных форматов, включая yaml.

from benedict import benedict

# path can be a yaml string, a filepath or a remote url
path = 'path/to/data.yml'

d = benedict.from_yaml(path)

# do stuff with your dict
# ...

# write it back to disk
d.to_yaml(filepath=path)

Это хорошо проверено и задокументировано, проверьте README, чтобы увидеть все функции: https://github.com/fabiocaccamo/python-benedict

Установите с помощью pip: pip install python-benedict

Ответ 4

Вы можете использовать пакет bios для python3, как показано ниже.

import bios

my_dict = bios.read('data.yml')

bios считывает необработанные данные из файла и конвертирует объект dict dict. По расширению файла он может определить тип файла.