简体   繁体   English

将 YAML 文件转换为 python dict

[英]Converting YAML file to python dict

I am having the following problem of mapping documents within a YAML file to a dict and properly mapping them.我在将 YAML 文件中的文档映射到dict并正确映射它们时遇到以下问题。

I have the following YAML file, which represents a server ( db.yml ):我有以下 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]

I load this YAML file, which I can do without any problems, I think I understand that.我加载了这个 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]

I'd like the logic to work like the following:我希望逻辑像下面这样工作:

  • load yaml, map to dict加载 yaml,映射到 dict
  • look in every dict in the document, if the instanceId matches that which was set by getInstanceId() , then print out all of the keys and values for that document.查看文档中的每个字典,如果instanceIdgetInstanceId()设置的匹配,则打印出该文档的所有键和值。

If I look at the map data structure from the command line, I get:如果我从命令行查看地图数据结构,我会得到:

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

I think I might be creating the data structure for the YAML file improperly, and on matching the contents on the dict , I am a bit lost.我想我可能没有正确地为 YAML 文件创建数据结构,并且在匹配dict上的内容时,我有点迷茫。

Side note: I cannot load all of the documents in this file using yaml.load() , I tried yaml.load_all() , which seems to work but my main issue still exists.旁注:我无法使用yaml.load()加载此文件中的所有文档,我尝试了yaml.load_all() ,这似乎有效,但我的主要问题仍然存在。

I think your yaml file should look like (or at least something like, so it's structured correctly anyway):我认为你的 yaml 文件应该是这样的(或者至少是类似的,所以它的结构是正确的):

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

Then, yaml.load(...) returns:然后, 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'}}

And you can go from there...你可以从那里去......


So used like:所以使用如下:

>>> 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

An additional bug in your code, that doesn't have to do with YAML:代码中的另一个错误,与 YAML 无关:

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

in is an operator that works on sequence types , and also on maps. in是一个适用于序列类型和映射的运算符。 This is why this isn't a syntax error... but it doesn't do what you want.这就是为什么这不是语法错误......但它没有做你想要的。

key in dict will always evaluate to True , because all the keys you're iterating through are in the dict. key in dict将始终评估为True ,因为您迭代的所有键都在 dict 中。 So your code boils down to True == "instanceId" , which will always evaluate to False , because the boolean value True is never equal to that string.所以你的代码归结为True == "instanceId" ,它总是评估为False ,因为布尔值True永远不等于该字符串。

You might have noticed that the print statement doesn't produce any output;您可能已经注意到print语句不产生任何输出; this is because it never gets called.这是因为它永远不会被调用。

Just use python-benedict , it's a dict subclass that provides I/O support for most common formats, including yaml .只需使用python-benedict ,它是一个 dict 子类,为大多数常见格式提供 I/O 支持,包括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)

It's well tested and documented, check the README to see all the features: https://github.com/fabiocaccamo/python-benedict它经过了良好的测试和记录,请查看自述文件以查看所有功能: https : //github.com/fabiocaccamo/python-benedict

Install using pip: pip install python-benedict使用 pip pip install python-benedictpip install python-benedict

Note: I am the author of this project注意:我是这个项目的作者

You can use the bios package for Python3 like below:您可以使用 Python3 的bios包,如下所示:

import bios

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

bios is reading the raw data from a file and converting a python dict object. bios正在从文件中读取原始数据并转换 python dict 对象。 According to the extension of the file, it can figure out the file type.根据文件的扩展名,可以判断文件类型。

If you have reached this question trying to figure out how to get a python dictionary from a yaml file using the pyyaml library try the safe_load option as shown below.如果您在尝试弄清楚如何使用 pyyaml 库从 yaml 文件中获取 python 字典时遇到了这个问题,请尝试如下所示的safe_load选项。

import yaml
dict = yaml.safe_load("data.yml")

I love to use Path, makes a beautiful one-liner我喜欢使用 Path,做一个漂亮的单线

import yaml
from pathlib import Path
conf = yaml.safe_load(Path('data.yml').read_text())

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM