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

我有三个模块:

>常量,包含类中的已加载配置和其他内容
> main,在运行时初始化常量
> user,导入常量并访问其配置.

常量模块(简化)看起来像这样:

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调用.

现在奇怪的事情发生了 – 当我从这样的用户导入常量模块时,常量是None:

from toplevelpkg.constants import constants
print(constants)

None

但是,如果我像这样导入它,常量会按照预期的方式初始化:

from toplevelpkg import constants
print(constants.constants)

<trumpet.constants.Constants object at 0x035AA130>

这是为什么?

编辑:在我的代码中,尝试读取常量的函数通过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是一个“全局”(在python中实际上意味着’模块级’,而不是’应用程序范围’)名称绑定到mymodule.obj导入时的名称(在你的情况下:无).从那时起,mymodule.obj和模块本地obj名称存在于不同的命名空间(mymodule命名空间中的第一个,当前模块命名空间中的第二个),并且从任何地方重新绑定mymodule.obj都不会改变什么当前模块的obj必然会被绑定.实际上,就像你这样做:

a = 2
b = a
a = 4

在第三个语句之后,b显然仍然是2 – 重绑定a到4不会影响b.

在第二种情况下(导入mymodule),在导入模块的命名空间中绑定的是整个mymodule对象,因此如果mymodule.obj被反弹(来自mymodule或其他任何地方),则导入模块中将显示更改.在这种情况下,它相当于

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

在这种情况下,变化将从b [“x”]可见,因为a和b仍然绑定到同一个对象.

wrt /你的问题:是的,拥有一些“配置”对象是一种非常常见的模式.您可能也想确保您可以“从头开始”构建它(我的意思是,不一定是从配置文件中)来使单元测试更容易.

转载注明原文:直接导入变量会产生与在Python中导入其模块不同的值 - 代码日志