Monkeypatching从.py文件加载的硬编码全局配置

时间:2013-09-12 20:58:00

标签: python python-2.7

一个同事有一个库,它使用在自己的文件中定义的硬编码配置。例如:

constants.py:

API_URL="http://example.com/bogus"

在整个库的其余部分,可以通过以下方式访问配置。

from constants import API_URL

您可以想象,这不是很灵活,在测试过程中会导致问题。如果我想更改配置,我必须修改constants.py,它位于源代码管理中。

当然,我更愿意从JSON或YAML文件加载配置。我可以将配置读入一个没有问题的对象。有没有办法可以在不破坏代码的情况下覆盖constants.py模块,以便每个全局,例如API_URL被我的文件提供的值替换?

我想在每个from constants import ...之后我可以添加这样的内容:

from constants import *  # existing configuration import
import json
new_config = json.load(open('config.json'))  # load my config file into a dictionary
constants.__dict__.update(new_config)        # override any constants with what I've loaded

当然,问题在于它不是很“干”,看起来可能很脆弱。

有没有人建议更干净地做这件事?谢谢!

编辑:看起来我的方法无论如何都不起作用。我猜“from import *”会将模块中的值复制到当前模块的全局范围内?

DOUBLE EDIT:不,它确实有效;我只是困惑。但是,如果可能的话,我希望让它透明地工作,而不是在X个不同的文件中执行此操作。

1 个答案:

答案 0 :(得分:1)

from module import <name>在导入模块全局命名空间中为导入的对象创建一个引用。如果那是不可变的,那意味着你现在必须对导入它的模块中的值进行monkeypatch。

你唯一的希望是成为第一个导入常量并monkeypatch该模块中的名称的人。然后,后续导入将使用您的monkeypatched值。

要尽早修补原始模块,以下就足够了:

import constants

for name, value in new_config.iteritems():
    setattr(constants, name, value)