单个文件 - 两个模块

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'>

证明模块是从同一来源创建的。