我正在使用 YAML 配置文件。所以这是在 Python 中加载我的配置的代码:
import os
import yaml
with open('./config.yml') as file:
config = yaml.safe_load(file)
这段代码实际上创建了一个字典。现在的问题是,为了访问我需要使用大量括号的值。
山药:
mysql:
user:
pass: secret
Python:
import os
import yaml
with open('./config.yml') as file:
config = yaml.safe_load(file)
print(config['mysql']['user']['pass']) # <--
我更喜欢这样的东西(点符号):
config('mysql.user.pass')
所以,我的想法是利用 PyStache render() 接口。
import os
import yaml
with open('./config.yml') as file:
config = yaml.safe_load(file)
import pystache
def get_config_value( yml_path, config ):
return pystache.render('{{' + yml_path + '}}', config)
get_config_value('mysql.user.pass', config)
那会是一个“好的”解决方案吗?如果没有,什么是更好的选择?
附加问题[已解决]
我决定使用 Ilja Everilä 的解决方案。但现在我有一个额外的问题:您将如何围绕 DotConf 创建一个包装器 Config 类?
以下代码不起作用,但我希望您了解我正在尝试做什么:
class Config( DotDict ):
def __init__( self ):
with open('./config.yml') as file:
DotDict.__init__(yaml.safe_load(file))
config = Config()
print(config.django.admin.user)
错误:
AttributeError: 'super' object has no attribute '__getattr__'
解决方案
您只需要将 self
传递给超类的构造函数。
DotDict.__init__(self, yaml.safe_load(file))
更好的解决方案(Ilja Everilä)
super().__init__(yaml.safe_load(file))
原文由 Lugaxx 发布,翻译遵循 CC BY-SA 4.0 许可协议
简单的
您可以使用
reduce
从配置中提取值:如果您的 YAML 使用非常有限的语言子集,则此解决方案易于维护并且几乎没有新的边缘情况。
正确的
使用适当的 YAML 解析器和工具,例如在 这个答案 中。
令人费解的
轻松一点(不要太认真),您可以创建一个允许使用属性访问的包装器:
请注意,这对“as”、“pass”、“if”等关键字无效。
最后,您可能会变得非常疯狂(阅读:可能不是一个好主意)并自定义
dict
将点分字符串和元组键作为一种特殊情况进行处理,对混合中抛出的项目进行属性访问(有其局限性):