单个文件 - 两个模块
Single file - two modules
每当我认为我理解了 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"
?
TL;DR: 是的,你有两个从 t1.py source.
原因在于 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'>
证明模块是从同一来源创建的。
每当我认为我理解了 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"
?
TL;DR: 是的,你有两个从 t1.py source.
原因在于 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'>
证明模块是从同一来源创建的。