解析yaml文件并获取字典
Parsing yaml file and getting a dictionary
我希望能够将下面定义的 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
理想情况下,我希望得到一个 returns 字典或 list
的解析函数,这样我就可以通过键名或使用 dot
运算符来访问属性:
print(config['development']['user'])
config.user
我哪里错了?
您的 "yaml" 不是映射的映射,而是字符串的映射。在 YAML 1.2 中,块映射条目 need whitespace after the separator,例如
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
不要尝试预处理此文本。相反,找到谁生成了标记和 throw the spec at them.
由于您无法立即通过 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 具有在白色 space 处换行(长)行的功能,这适用于不带引号的标量,例如您的
user:dev_uid
pass:dev_pwd
host:127.0.0.1
database:dev_db
您的 YAML 文件相当于:
发展:"user:dev_uid pass:dev_pwd host:127.0.0.1 database:dev_db"
生产:"user:uid pass:pwd host:127.0.0.2 database:db"
然后到
发展:user:dev_uid pass:dev_pwd host:127.0.0.1 database:dev_db
生产:user:uid pass:pwd host:127.0.0.2 database:db
因为不需要引号,因为不会混淆 development
的值是一个映射,至于键后面的冒号应该跟一个 space。这可以从用于实现 PyYAML¹ 的旧版(现已过时)YAML 1.1 specification 中看出。
最好是转换、更正 YAML,如果您可以假设 none 的键和值已嵌入 spaces:
,这很容易完成
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)
如果您的文件比您提供的文件更复杂,您可能需要重复使用字典值和列表项,这很简单。
以上输出:
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 在使用流式映射时允许在冒号后不带 space 的键值对。但前提是键和值都被(双)引号。此更改对于允许 YAML 1.2 与 JSON:
兼容是必要的
development: {
"user":"dev_uid",
"pass":"dev_pwd",
"host":"127.0.0.1",
"database":"dev_db"
}
我希望能够将下面定义的 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
理想情况下,我希望得到一个 returns 字典或 list
的解析函数,这样我就可以通过键名或使用 dot
运算符来访问属性:
print(config['development']['user'])
config.user
我哪里错了?
您的 "yaml" 不是映射的映射,而是字符串的映射。在 YAML 1.2 中,块映射条目 need whitespace after the separator,例如
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
不要尝试预处理此文本。相反,找到谁生成了标记和 throw the spec at them.
由于您无法立即通过 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 具有在白色 space 处换行(长)行的功能,这适用于不带引号的标量,例如您的
user:dev_uid
pass:dev_pwd
host:127.0.0.1
database:dev_db
您的 YAML 文件相当于:
发展:"user:dev_uid pass:dev_pwd host:127.0.0.1 database:dev_db" 生产:"user:uid pass:pwd host:127.0.0.2 database:db"
然后到
发展:user:dev_uid pass:dev_pwd host:127.0.0.1 database:dev_db 生产:user:uid pass:pwd host:127.0.0.2 database:db
因为不需要引号,因为不会混淆 development
的值是一个映射,至于键后面的冒号应该跟一个 space。这可以从用于实现 PyYAML¹ 的旧版(现已过时)YAML 1.1 specification 中看出。
最好是转换、更正 YAML,如果您可以假设 none 的键和值已嵌入 spaces:
,这很容易完成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)
如果您的文件比您提供的文件更复杂,您可能需要重复使用字典值和列表项,这很简单。
以上输出:
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 在使用流式映射时允许在冒号后不带 space 的键值对。但前提是键和值都被(双)引号。此更改对于允许 YAML 1.2 与 JSON:
兼容是必要的development: {
"user":"dev_uid",
"pass":"dev_pwd",
"host":"127.0.0.1",
"database":"dev_db"
}