直接导入变量产生的值与在 Python 中导入其模块产生的值不同

Importing variable directly yields a different value than importing its module in Python

我有三个模块:

constants 模块(简化)如下所示:

class Constants:
    def __init__(self, filename):
        # Read values from INI file
        config = self.read_inifile(filename)
        self.somevalue = config['ex']['ex']

    def read_inifile(self, filename):
        # reads inifile

constants: Constants = None

def populate_constants(filename):
    global constants
    constants = Constants(filename)

一个应该包含配置的简单对象,没有什么开创性的。

函数 populate_constants() 在程序启动时从 main 调用。

现在奇怪的事情发生了 - 当我像这样从 user 导入 constants 模块时,constantsNone:

from toplevelpkg.constants import constants
print(constants)

None

但是,如果我这样导入它,constants 会像预期的那样被初始化:

from toplevelpkg import constants
print(constants.constants)

<trumpet.constants.Constants object at 0x035AA130>

这是为什么?

编辑:在我的代码中,尝试读取 constants 的函数是 运行 通过 await loop.run_in_executor(None, method_needing_import) 异步读取的。不确定这是否会导致问题?

(作为一个附带问题,拥有一个解析配置文件并将其作为其成员变量提供的配置保存对象是一种好习惯吗?)

确实有区别
from mymodule import obj
(...)
do_something_with(obj)

import mymodule
(...)
do_something_with(mymodule.obj)

在第一种情况下,它充当:

 import mymodule
 obj = mymodule.obj
 del mymodule

这意味着此时,在当前模块中,obj是一个"global"(在python中实际上意味着'module-level',而不是'application-wide') 名称绑定到任何 mymodule.obj 当它被导入时 (在你的例子中: None)。从那时起,mymodule.obj 和模块本地 obj 名称位于不同的命名空间中(第一个在 mymodule 命名空间中,第二个在当前模块命名空间中),并重新绑定 mymodule.obj 来自任何地方都不会改变当前模块的 obj 所绑定的内容。实际上,就像你这样做一样:

a = 2
b = a
a = 4

在第三条语句之后,b 显然仍然绑定到 2 - 将 a 重新绑定到 4 不会影响 b

在第二种情况下 (import mymodule) 在导入模块的命名空间中绑定的是整个 mymodule 对象,因此如果 mymodule.obj 被反弹(从 mymodule 或其他任何地方)更改将在导入模块中可见。在这种情况下,它等同于

a = {"x": 2}
b = a
a["x"] = 4

在这种情况下,更改也将从 b["x"] 可见,因为 ab 仍然绑定到同一个对象。

wrt/ 你的附带问题:是的,有一些 "config" 对象是很常见的模式。您可能只是想确保您也可以构建它 "from scratch"(我的意思是,不一定来自配置文件)以使单元测试更容易。