__name__ == "__main__" 是Python解释器硬编码的模块加载机制,用于区分直接执行(此时__name__为"__main__")与被导入(此时为模块名),从而控制测试代码或主逻辑仅在直接运行时执行。

为什么 __name__ == "__main__" 能判断运行方式
Python 在加载模块时,会把当前模块的 __name__ 属性设为 "__main__" —— 仅当它是被直接执行(如 python script.py)时;如果被其他模块 import,它的 __name__ 就是模块文件名(不含 .py),比如 "utils"。这个机制不是约定,而是解释器硬编码的行为。
常见错误现象:把测试代码写在模块顶层,结果一导入就执行,导致副作用(如发起网络请求、删文件、打印日志)。用 if __name__ == "__main__": 包裹后,这部分只在直接运行时触发。
- 必须严格写成
__name__ == "__main__",多一个空格、大小写错误或引号类型(如用中文引号)都会失效 -
__name__是模块级变量,不能在函数内用它判断“当前函数是否被直接调用”——那是设计问题,得靠参数或上下文 - 在交互式环境(如 IPython)中,
__name__总是"__main__",但此时没有“脚本入口”概念,该判断逻辑不适用
实际怎么写才安全可靠
典型结构是把可执行逻辑封装成函数,再在 if __name__ == "__main__": 下调用。不推荐把大段代码直接塞进条件块里,既难测试又难复用。
def main():
print("运行核心逻辑")
# 这里放你的主流程
<p>if <strong>name</strong> == "<strong>main</strong>":
main()- 函数名不强制叫
main,但这是通用惯例,也方便后续加命令行参数解析(如用argparse) - 如果模块需要支持两种用法(直接运行 + 导入后调用函数),就把功能拆到独立函数里,别让
if __name__ == "__main__"块承担业务逻辑 - 避免在
if __name__ == "__main__":里修改全局状态(如重置配置、清空缓存),除非你明确知道导入者不会受影响
被导入时 __name__ 真的是模块名吗
是的,但要注意包路径。比如项目结构是 project/ → pkg/ → submod.py,从项目根目录运行 python -m pkg.submod,该模块的 __name__ 是 "pkg.submod",不是 "__main__";只有用 python pkg/submod.py 才会是 "__main__"。
立即学习“Python免费学习笔记(深入)”;
- 用
-m参数运行模块时,它仍是被“导入”执行的,所以__name__不是"__main__" - 如果你希望
-m方式也能触发主逻辑,得在模块里额外判断sys.argv[0].endswith("__main__.py")或类似方式——但通常没必要,统一用直接执行即可 - 动态导入(如
importlib.import_module("xxx"))同样遵循规则:__name__是模块全名,不是"__main__"
容易被忽略的边界情况
最常踩的坑是误以为 __name__ 能反映“谁调用了我”。它只说明当前模块如何被加载,和调用栈无关。比如 A.py 导入 B.py,B.py 中的 __name__ 永远是 "B",哪怕 A.py 正在执行。
- 不要在库模块里写
if __name__ == "__main__":来做初始化——库应该由使用者显式调用初始化函数 - 打包成可执行文件(如 PyInstaller)后,
__name__仍按原始逻辑工作,但主脚本的__name__依然是"__main__" - 多进程场景下,子进程启动新解释器实例,每个进程里的主模块
__name__都是"__main__",需注意重复初始化
真正要区分“是否作为程序入口”,靠的就是这一行判断;但别指望它解决所有执行上下文问题——它只是 Python 加载机制的一个开关,不是万能上下文探测器。


















