Преобразование файла 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. По расширению файла он может определить тип файла.