windows必须用if name == "__main__",因其无fork(),子进程需重新导入模块并执行顶层代码,若未加保护会导致无限递归创建进程,直至资源耗尽。

Windows 下不加 if __name__ == "__main__" 会导致子进程无限递归创建,直到系统资源耗尽或报错退出。
为什么 Windows 必须用 if __name__ == "__main__"
因为 Windows 没有 fork() 系统调用。Linux/macOS 启动子进程时直接复制主进程内存状态,子进程从 fork() 返回点继续执行,不会重新导入模块、也不会重复执行模块顶层代码。而 Windows 只能靠“新起一个 Python 解释器 + 重新导入主模块”来模拟多进程 —— 这意味着:每个子进程启动时,都会完整执行一遍你的脚本文件所有顶层语句。
如果你的脚本里直接写了 multiprocessing.Process(...).start() 或 multiprocessing.Pool(),那每个子进程在导入时也会执行这行,进而再 spawn 更多子进程……形成雪崩式递归。
通过 SSH 隧道从 Android 设备在互联网上对 Windows PC 实现完整远程控制的设置与使用指南,适用于远程桌面访问、安全 RDP 等。
- 错误现象:
OSError: [WinError 87] 参数错误或 CPU 占用飙到 100%、几秒后卡死 - 哪怕只写了一行
p = Process(target=f); p.start(),没包在if __name__ == "__main__"里,就足以触发该问题 - 这个限制不是“建议”,而是 Windows 平台下
multiprocessing模块的运行前提
if __name__ == "__main__" 在子进程中值是什么
在子进程中,__name__ 的值是 '__mp_main__'(Python 3.8+)或 '__main__'(旧版本),但关键在于:它**永远不等于你在主脚本里写的字符串 "__main__" 所对应的模块入口逻辑** —— 因为子进程不是“直接运行”该脚本,而是被父进程通过模块导入机制拉起来的。
- 所以
if __name__ == "__main__"块里的代码,在子进程中根本不会进入 - 你可以在里面安全地初始化
Pool、启动Process、读取大文件、连接数据库等 —— 这些操作只在原始主进程中执行一次 - 注意:不要在
if __name__ == "__main__"外定义全局变量并期望子进程能访问它;Windows 下子进程无法继承主进程对象,必须显式传参或用Manager/Queue
常见误用场景和修复方式
最容易被忽略的是“模块封装后仍出问题”。比如你把多进程逻辑写在 worker.py 里,又在 main.py 中 import worker 并调用函数 —— 如果 worker.py 自己没加 if __name__ == "__main__",而它内部又有 if __name__ == "__main__": ...,那没问题;但如果它顶层就写了 Process(...).start(),那么只要被任何脚本 import,就会立刻触发递归。
- 错误写法:
worker.py顶部直接写p = Process(target=do_work); p.start() - 正确写法:把启动逻辑收进函数,如
def run_workers(): ...,并在if __name__ == "__main__": run_workers()中调用 - 如果使用
concurrent.futures.ProcessPoolExecutor,同样需要包裹 —— 它底层也是multiprocessing - PyInstaller 打包后运行出错?大概率是打包脚本没加
if __name__ == "__main__",导致 exe 启动时反复 fork
真正容易被忽略的点是:这个保护不是为了“让代码看起来规范”,而是 Windows 下防止解释器崩溃的硬性屏障。哪怕你只在本地测试、只跑一次,漏掉它也可能让机器风扇狂转、任务管理器卡住 —— 不是因为代码慢,是因为它正在启动成百上千个进程。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










