将YAML文件转换为python dict

Zip*_*oli 34 python dictionary yaml data-structures

我有一个问题,即将YAML文件中的文档映射到dict并正确映射它们.

我有以下YAML文件,它代表一个server(db.yml):

instanceId: i-aaaaaaaa
     environment:us-east
     serverId:someServer
     awsHostname:ip-someip
     serverName:somewebsite.com
     ipAddr:192.168.0.1
     roles:[webserver,php]
Run Code Online (Sandbox Code Playgroud)

我加载这个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]
Run Code Online (Sandbox Code Playgroud)

我希望逻辑像以下一样工作:

  • 加载yaml,映射到dict
  • 查看文档中的每个字典,如果instanceId匹配的是getInstanceId(),则打印出该文档的所有键和值.

如果我从命令行查看地图数据结构,我得到:

{'instanceId': 'i-aaaaaaaa environment:us-east serverId:someServer awsHostname:ip-someip serverName:someserver ipAddr:192.168.0.1 roles:[webserver,php]'}
Run Code Online (Sandbox Code Playgroud)

我想我可能是不正确地为YAML文件创建数据结构,并且在匹配内容时dict,我有点迷失.

旁注:我无法加载此文件中的所有文件yaml.load(),我试过yaml.load_all(),这似乎有用,但我的主要问题仍然存在.

Jon*_*nts 35

我认为你的yaml文件应该看起来像(或者至少是类似的,所以它的结构正确无论如何):

instance:
     Id: i-aaaaaaaa
     environment: us-east
     serverId: someServer
     awsHostname: ip-someip
     serverName: somewebsite.com
     ipAddr: 192.168.0.1
     roles: [webserver,php]
Run Code Online (Sandbox Code Playgroud)

然后,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'}}
Run Code Online (Sandbox Code Playgroud)

你可以从那里去......


所以使用像:

>>> 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
Run Code Online (Sandbox Code Playgroud)

  • 由于没有名为“yaml”的内置模块,并且有多个具有该名称的第三方库,因此问题可能是您使用的库与答案中的库不同。我验证了 PyYAML 3.10(都是带有 libyaml 0.1.4 的纯 Python)给出了@JonClements 显示的答案,simpleyaml 3.10 也是如此。也许您有一个损坏的库(这也可以解释为什么您首先要尝试解析损坏的 yaml?)。 (2认同)

Pro*_*rox 21

我喜欢使用 Path,制作出漂亮的单行文字

import yaml
from pathlib import Path
conf = yaml.safe_load(Path('data.yml').read_text())
Run Code Online (Sandbox Code Playgroud)


Mic*_*per 7

代码中的另一个错误,与 YAML 无关:

for key in dict:
    if key in dict == "instanceId": # This doesn't do what you want
        print key, dict[key]
Run Code Online (Sandbox Code Playgroud)

in是一个操作符,适用于序列类型,也适用于映射。这就是为什么这不是语法错误......但它没有做你想要的。

key in dict将始终评估为True,因为您迭代的所有键都在 dict 中。所以你的代码归结为True == "instanceId",它总是计算为False,因为布尔值True永远不等于该字符串。

您可能已经注意到该print语句不产生任何输出;这是因为它永远不会被调用。


Fab*_*amo 6

只需使用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)
Run Code Online (Sandbox Code Playgroud)

它经过了充分的测试和记录,请检查自述文件以查看所有功能: https: //github.com/fabiocaccamo/python-benedict

使用 pip 安装:pip install python-benedict

注:我是该项目的作者


naj*_*eem 6

如果您遇到这个问题,试图弄清楚如何使用 pyyaml 库从 yaml 文件获取 python 字典,请尝试safe_load如下所示的选项。

import yaml
from pathlib import Path

yaml_dict = yaml.safe_load(Path("data.yml").read_text())
Run Code Online (Sandbox Code Playgroud)