在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模块有很长的代码要执行,并且在第二个导入获取一个时隙之前还没有完成,该怎么办?如果我使用多处理,整个系统将会变成什么样?
不幸的是,我没有找到很好的解释。
所以,我已经测试了它在基本设置中的工作原理,我已经知道了很多,我的问题是为什么它如此工作,其基本机制是什么?
答案 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
,通常这不是问题。