2

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

常量.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

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

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

编辑:看起来我的方法无论如何都行不通。我猜“从导入*”将模块中的值复制到当前模块的全局范围内?

双重编辑:不,它确实有效;我只是困惑。但与其在 X 个不同的文件中执行此操作,我希望尽可能让它透明地工作。

4

1 回答 1

1

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

您唯一的希望是成为第一个导入常量并猴子补丁该模块中的名称的人。随后的导入将使用您的猴子补丁值。

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

import constants

for name, value in new_config.iteritems():
    setattr(constants, name, value)
于 2013-09-13T17:44:26.047 回答