具有多个导入的Python模块全局变量

时间:2019-06-19 11:02:17

标签: python import module

在python中导入模块时,运行什么代码,什么不运行?

在python中第二次导入模块 时,运行什么代码,什么不运行?

module1.py

GLOBAL_VAR = 'orig'

print('module1: GLOBAL_VAR = {}'.format(GLOBAL_VAR))

def init():
    global GLOBAL_VAR
    print('module1:init(1): GLOBAL_VAR = {}'.format(GLOBAL_VAR))
    GLOBAL_VAR = 'changed'
    print('module1:init(2): GLOBAL_VAR = {}'.format(GLOBAL_VAR))

module2.py

print('module2: importing module1')
import module1

print('module2(1): module1.GLOBAL_VAR = {}'.format(module1.GLOBAL_VAR))

module1.init()

print('module2(2): module1.GLOBAL_VAR = {}'.format(module1.GLOBAL_VAR))

module3.py

print('module3: importing module1')
import module1

print('module3(1): module1.GLOBAL_VAR = {}'.format(module1.GLOBAL_VAR))

main.py

import module2
import module3

输出

python3 main.py

module2: importing module1
module1: GLOBAL_VAR = orig
module2(1): module1.GLOBAL_VAR = orig
module1:init(1): GLOBAL_VAR = orig
module1:init(2): GLOBAL_VAR = changed
module2(2): module1.GLOBAL_VAR = changed
module3: importing module1
module3(1): module1.GLOBAL_VAR = changed

基本上,“独立式”-不在函数中,不在类中-代码仅运行一次。我想进一步了解这一点,这是如何工作的,有哪些局限性,尤其是什么时候不正确?

我的直觉是,即使导入的模块是从不同的模块导入的,也要在“每个解释器”级别进行注册,并且解释器知道模块中的代码是否已经运行,然后,它将维护对象中任何模块的当前状态,每个导入程序都会获取该维护的对象。

但是什么会弄乱呢?如果我使用线程,并且第二个模块导入了X模块,但是X模块有很长的代码要执行,并且在第二个导入获取一个时隙之前还没有完成,该怎么办?如果我使用多处理,整个系统将会变成什么样?

不幸的是,我没有找到很好的解释。

所以,我已经测试了它在基本设置中的工作原理,我已经知道了很多,我的问题是为什么它如此工作,其基本机制是什么?

1 个答案:

答案 0 :(得分:0)

您正确地说所有顶级代码都是在首次导入时执行的。其中包括将函数名称绑定到函数对象的函数定义(但不包括它们的主体)。

模块一旦导入,就会存储在sys.modules中。这是dict映射模块名称到模块对象。因此,在import module_a之后,您可以将其称为sys.modules['module_a']。您甚至可以将其从dict中删除(这样做的后果请参见What does "del sys.modules[module]" actually do?)。 如果您不从sys.modules删除模块,则所有以后的导入都将从那里获取对象。您可以在这里找到导入系统的详细说明:https://docs.python.org/3/reference/import.html

对于多线程,由于全局解释器锁(GIL):https://docs.python.org/3/c-api/init.html?highlight=gil#thread-state-and-the-global-interpreter-lock

,通常这不是问题。