在Python3中使用ruamel.yaml解析Yaml嵌套配置

伊斯玛·斯洛米奇

使用Python软件包解析YAML配置文件时,ruamel.yaml我需要考虑到可以在同一YAML文件中以两种不同的样式描述嵌套:

  1. 通过使用换行和缩进
  2. 通过使用点(。)

简化示例:

运行repl.it代码段

logging.yml

# 1. by using new line and indents
logging: 
  file: 
    name: app.log
# 2. by using dots (.)
logging.file.path: /logs

main.py

#!/usr/bin/env python3

import ruamel.yaml as yaml

with open('logging.yml', 'r') as file:
  data = yaml.safe_load(file)
print(data)

实际输出

{
  'logging': {
    'file': {
      'name': 'app.log'
    }
  },
  'logging.file.path': '/logs'
}

是否可以通过ruamel.yaml某种方式进行配置,以便我可以如下所述将path属性嵌套在logging-> file中,以便以后可以轻松访问该属性?

{
  'logging': {
    'file': {
      'name': 'app.log',
      'path': '/logs'
    }
  }
}
安通

不,无法ruamel.yaml按照您想要的方式进行配置我什至认为尝试创建一个在加载过程中即时执行所需操作的构造函数是一个坏主意,因为例如,这意味着您在解析映射即键值时需要考虑到这一点file,拆分后可能已经存在一个python字典logging.file.path

我建议您对以下内容进行后处理data

from pprint import pprint
import ruamel.yaml

yaml_str = """\
logging: 
  file: 
    name: app.log
logging.file.path: /logs
"""


yaml = ruamel.yaml.YAML(typ='safe')
data = yaml.load(yaml_str)
for k in list(data.keys()):
    if not '.' in k:
        continue
    keys = k.split('.')
    d = data
    while len(keys) > 1:
        d = d.setdefault(keys.pop(0), {})
    d[keys[0]] = data.pop(k)
pprint(data, width=-1)

这使:

{'logging': {'file': {'name': 'app.log',
                      'path': '/logs'}}}

如有必要,您可以递归地执行此操作,以防万一您拥有在根级别不存在带点的键。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章