Python中无if __name__ == "__main__"校验的自导入模块为何未无限递归?
foo3.py 代码执行逻辑解释
首先先给出你提到的无if __name__ == "__main__"校验的foo3.py示例代码:
# foo3.py print("t1") def functionA(): print("a1") import foo3 print("a2") print("m1") functionA() print("m3")
核心前提
Python 有模块导入缓存机制:每个模块首次被导入时,会完整执行一次模块顶层代码,之后会将模块对象存入sys.modules字典缓存,后续再导入同一个模块时,直接返回缓存的模块对象,不会重复执行模块顶层代码,这就是不会触发无限递归的根本原因。
运行python3 foo3.py的完整执行顺序
- 步骤1:当前foo3.py作为入口程序启动,此时对应模块的
__name__值为__main__,从上到下执行顶层代码:- 执行
print("t1"),输出t1 - 完成
functionA函数的定义(仅注册函数对象,不执行内部逻辑) - 执行
print("m1"),输出m1 - 调用
functionA(),进入函数内部执行
- 执行
- 步骤2:进入
__main__模块的functionA执行:- 执行
print("a1"),输出a1 - 执行
import foo3:此时检查sys.modules,入口程序对应的模块名是__main__,不存在名为foo3的缓存,因此正式加载foo3.py作为名为foo3的模块,重新执行该文件的顶层代码
- 执行
- 步骤3:执行名为
foo3的模块的顶层代码:- 执行
print("t1"),输出t1 - 完成
foo3模块下functionA函数的定义(和__main__模块的functionA是独立的两个函数对象) - 执行
print("m1"),输出m1 - 调用
foo3模块下的functionA(),进入该函数执行
- 执行
- 步骤4:进入
foo3模块的functionA执行:- 执行
print("a1"),输出a1 - 执行
import foo3:检查sys.modules,名为foo3的模块已经在步骤3加载并存入缓存,直接返回缓存对象,不重复执行foo3.py顶层代码 - 执行
print("a2"),输出a2 - 该函数执行完毕,返回步骤3的调用点
- 执行
print("m3"),输出m3 foo3模块加载完成,返回步骤2的import foo3调用点
- 执行
- 步骤5:回到
__main__模块的functionA继续执行:- 执行
print("a2"),输出a2 - 该函数执行完毕,返回步骤1的调用点
- 执行
print("m3"),输出m3 - 整个程序执行结束
- 执行
最终输出顺序为:
t1 m1 a1 t1 m1 a1 a2 m3 a2 m3
内容的提问来源于stack exchange,提问作者Milan
相关产品推荐
相关产品推荐

