Python 解析yaml文件并获取字典

Python 解析yaml文件并获取字典,python,pyyaml,Python,Pyyaml,我希望能够将下面定义的YAML转换成字典 development: user:dev_uid pass:dev_pwd host:127.0.0.1 database:dev_db production: user:uid pass:pwd host:127.0.0.2 database:db 我已经能够使用YAML库来加载数据。但是,我的字典似乎包含一个长字符串形式的环境项 此代码: #!/usr/bin/python3 i

我希望能够将下面定义的YAML转换成字典

development:
    user:dev_uid
    pass:dev_pwd
    host:127.0.0.1
    database:dev_db

production:
    user:uid
    pass:pwd
    host:127.0.0.2
    database:db
我已经能够使用YAML库来加载数据。但是,我的字典似乎包含一个长字符串形式的环境项

此代码:

#!/usr/bin/python3

import yaml

config  = yaml.load(open('database.conf', 'r'))

print(config['development'])
产生以下输出

user:dev_uid pass:dev_pwd host:127.0.0.1 database:dev_db
我无法按键名访问任何条目,也无法使用
yaml.load
方法加载该字符串

print(config['development']['user'])
此代码产生以下错误:

TypeError: string indices must be integers
理想情况下,我希望最终得到一个解析函数,该函数返回一个字典或
列表
,这样我就可以通过键名或使用
操作符访问属性,如:

print(config['development']['user'])
config.user
我哪里出错了?

您的“yaml”不是映射的映射,而是字符串的映射。在YAML 1.2中,块映射条目,例如


不要试图预处理此文本。相反,请查找是谁生成了标记,并且。

由于您无法立即使用
yaml
模块获得所需的内容,因此.conf文件可能使用的格式与
yaml
模块当前期望的格式不同

此代码是一种快速解决方法,可为您提供所需的词典:

for mainkey in ['production','development']:
    d = {}
    for item in config[mainkey].split():
        key,value = item.split(':')
        d[key] = value
    config[mainkey] = d

您的YAML是绝对有效的,这就是为什么在加载此文件时不会出现错误的原因。它没有像您期望的那样加载是因为YAML有一个以空格换行(长)的特性,这适用于不带引号的标量,例如

user:dev_uid
pass:dev_pwd
host:127.0.0.1
database:dev_db
您的YAML文件相当于:

开发:“用户:dev_uid pass:dev_pwd主机:127.0.0.1数据库:dev_db” 生产:“用户:uid密码:pwd主机:127.0.0.2数据库:db”

以及

开发:用户:dev_uid pass:dev_pwd主机:127.0.0.1数据库:dev_db 生产:用户:uid密码:pwd主机:127.0.0.2数据库:db

因为引号是不必要的,因为对于
development
作为映射的值不会有任何混淆,因为键后面的冒号应该跟一个空格。这可以从用于实现PyYAMLñ的旧版本(现在已经过时)中看出

最好的方法是转换、更正YAML,如果您可以假设所有键和值都没有嵌入空格,则可以轻松完成此操作:

import sys
import yaml


yaml_str = """\
development:
    user:dev_uid
    pass:dev_pwd
    host:127.0.0.1
    database:dev_db

production:
    user:uid
    pass:pwd
    host:127.0.0.2
    database:db
"""

data = yaml.safe_load(yaml_str)
for key in data:
    val = data[key]
    if ':' not in val:
        continue
    data[key] = tmp = {}
    for x in val.split():
        x = x.split(':', 1)
        tmp[x[0]] = x[1]

yaml.safe_dump(data, sys.stdout, default_flow_style=False)
如果您的文件比您所呈现的更复杂,那么您可能必须递归到dict值和列表项中,这相当简单

上述产出:

development:
  database: dev_db
  host: 127.0.0.1
  pass: dev_pwd
  user: dev_uid
production:
  database: db
  host: 127.0.0.2
  pass: pwd
  user: uid
然后按照您的预期加载,而不会带来麻烦


较新的YAML 1.2允许在使用流样式映射时,在冒号后没有空格的键值对。但前提是关键和价值都要(双重)引用。此更改对于允许YAML 1.2与JSON兼容是必要的:

development: {
    "user":"dev_uid",
    "pass":"dev_pwd",
    "host":"127.0.0.1",
    "database":"dev_db"
  }

除非您使用指定Python内部对象的标记(几乎没有人这样做),否则没有必要使用
yaml.load()
,这被证明是不安全的。始终使用
yaml.safe_load()
代替。那就是我:(谢谢你的帮助!从上周开始,我就被这个问题弄糊涂了-这是我看到的第一个YAML项目提到了空格的重要性!我从其他我读过的文章中没有任何线索。。。。。。
development: {
    "user":"dev_uid",
    "pass":"dev_pwd",
    "host":"127.0.0.1",
    "database":"dev_db"
  }