【不背八股】1.if __name__ == "__main__" 有什么作用?

起名动机

最近开始准备秋招,技术圈惯例会把常见的面试问答题戏称为"八股文",网上流传不少这样的材料,写得晦涩难懂,以至于让好多求职者去背诵

在我看来,用文科思维学工科毫无意义,八股实际就是一些基础计算机科学知识,如何用清晰地方式去理解,实践,应用才更有价值。

因此,打算开个新的系列文章[不背八股],用一种全新的表述方式,重新理解八股面试题。

从一个报错开始

在项目实践中,遇到报错:

vbnet 复制代码
RuntimeError:
        An attempt has been made to start a new process before the
        current process has finished its bootstrapping phase.

        This probably means that you are not using fork to start your
        child processes and you have forgotten to use the proper idiom
        in the main module:

            if __name__ == '__main__':
                freeze_support()
                ...

        The "freeze_support()" line can be omitted if the program
        is not going to be frozen to produce an executable.

        To fix this issue, refer to the "Safe importing of main module"
        section in https://docs.python.org/3/library/multiprocessing.htm

DeepSeek**给出的解释是:

若主模块未保护入口点(即缺少 if name == 'main':),会导致子进程重复执行主模块代码。

将主代码移至if __name__ == '__main__':下之后,果然问题解决了。

这不由让我进一步思考:多数情况下,把这个操作作为一种惯例,没有思考过为什么要这么做,这么做为什么有效。

正好看到一道面试题:if __name__ == "__main__"有什么作用?借此把这个问题再探究一下。

__name__是什么?

首先要理解__name__的作用。

__name__ 是 Python 在加载模块(文件)时,解释器自动设置的一个全局变量,用来标识这个模块的"名称"。

举个简单的例子,创建一个hello.py

bash 复制代码
print("我是:", __name__)

运行输出结果:

markdown 复制代码
我是: __main__

再建立一个新的文件test.py,去导入这个文件

arduino 复制代码
import hello

运行输出结果:

复制代码
我是: hello

因此可以得到结论:

  • __name__在直接运行时值为"main"
  • __name__被导入时值为模块名

当运行一个 Python 文件,或者通过 import 导入一个模块,解释器隐式去做这件事:

ini 复制代码
# 如果是直接运行
import types

module = types.ModuleType("__main__")  # 创建模块对象
module.__name__ = "__main__"
exec(open("foo.py").read(), module.__dict__)  # 执行代码

# 如果是模块导入
import importlib

spec = importlib.util.find_spec("模块名称")
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)

因此,在一些模块中,往往会看到用if __name__ == "__main__"包裹的代码块,用来执行单元测试(cell test)。

多进程启动问题

下面回到开篇遇到的问题,为什么会出现这个error。

可以用以下代码,最小程度复现出该问题:

scss 复制代码
from multiprocessing import Process


def worker():
    print("子进程")


p = Process(target=worker)
p.start()

实际上,该问题只会在WindowsmacOS平台上发生。

对于Python 多进程(multiprocessing),Windows 和 macOS 默认采用spawn的方式进行启动。

它会新开一个空白的 Python 解释器进程,去重新导入主模块,因为主模块没放置在if __name__ == "__main__"之中,它被导入时,又会被再次执行一下,这就导致无限递归执行,出现此问题。

Linux 采用 fork 的方式,操作系统会直接复制当前进程的内存和运行状态,不会重新执行主模块,因此不会出现该问题。

项目 Linux Windows/macOS
启动方式 fork spawn
主模块会不会重新执行 ❌ 否 ✅ 是
是否必须加 if __name__ == '__main__' 推荐 ✅ 必须
报错可能性 较低 较高(会崩)
相关推荐
凯子坚持 c10 小时前
StreamingLLM:无需训练即可支持无限上下文的推理技术
人工智能
Tfly__10 小时前
在PX4 gazebo仿真中加入Mid360(最新)
linux·人工智能·自动驾驶·ros·无人机·px4·mid360
LLWZAI10 小时前
让朱雀AI检测无法判断的AI公众号文章,当创作者开始与算法「躲猫猫」
大数据·人工智能·深度学习
深圳市九鼎创展科技10 小时前
瑞芯微 RK3399 开发板 X3399 评测:高性能 ARM 平台的多面手
linux·arm开发·人工智能·单片机·嵌入式硬件·边缘计算
Σίσυφος190010 小时前
PCL法向量估计 之 RANSAC 平面估计法向量
算法·机器学习·平面
HELLO程序员10 小时前
Claude Code 2.1 发布:2026 年 AI 智能体开发的范式革命
人工智能
xhbaitxl10 小时前
算法学习day39-动态规划
学习·算法·动态规划
I_LPL11 小时前
day23 代码随想录算法训练营 回溯专题2
算法·hot100·回溯算法·求职面试
智者知已应修善业11 小时前
【洛谷P9975奶牛被病毒传染最少数量推导,导出多样例】2025-2-26
c语言·c++·经验分享·笔记·算法·推荐算法
DFCED11 小时前
OpenClaw部署实战:5分钟搭建你的专属AI数字员工(附避坑指南)
人工智能·大模型·agent·openclaw