每次我认为我理解Python导入的细节(最后!),新的东西让我回到了现实。请看一下这个简单的例子:
档案t1.py
:
import t2
x = "waiting for init"
def init():
global x
x = "OK"
if __name__ == '__main__':
init()
print("x =", x)
t2.print_x()
注意不要使用错误的from t1 import x
,这里是文件t2.py
:
import t1
def print_x():
print("t1.x =", t1.x)
无论如何,输出不是我的预期:
$ python3 t1.py
x = OK
t1.x = waiting for init
因此x in t1
与t1.x
不同!
经过一番调查后,这个版本的t2.py
对我有所帮助:
import t1
def print_x():
import sys
print(sys.modules['t1'].x)
print(sys.modules['__main__'].x)
这两张照片的输出是:
waiting for init
OK
我发现它令人困惑。单个文件t1.py
同时称为两个不同的模块:t1
和__main__
。你能解释一下它的含义吗?在发布的代码中必须更改哪些内容才能获得t1.x = "OK"
?
答案 0 :(得分:1)
TL; DR :是的,您有两个从 t1.py 源创建的内存模块。
这是因为Python的导入系统处理__main__
模块的原因。基本上,它不会这样做。
__main__
模块不是通过Python的标准导入机制导入的,而是与内置函数的初始化类似。
这就是为什么,当您在代码中从t1
导入t1
时,您实际上会再次导入 。
进行实验很容易。将t1.py
模块的代码更改为:
import t2
x = "waiting for init"
if __name__ == "t1":
print("t1.x = ", x)
if __name__ == '__main__':
print("__main__.x =", x)
你会看到下一个打印在控制台中:
t1.x = waiting for init
__main__.x = waiting for init
现在评论此模块中的第一行,您将得到:
__main__.x = waiting for init
因此,在第一种情况下,模块t1
首先由解释器的启动机制初始化(其代码被执行)为__main__
,然后t1由Python的导入系统从t2模块初始化(因此是再次执行。)
在第二种情况下,模块仅由解释器启动机制初始化。
PS。来自@ShadowRanger的好评如下:在脚本末尾打印sys.modules
将显示如下内容:
<module '__main__' from 't1.py'>
<module 't1' from 'D:\\Projects\\python_test\\t1.py'>
演示模块是从同一个源创建的。