当前位置:首页>python>Python 中 if _ _name_ _ == '_ _main_ _' 到底是什么意思?

Python 中 if _ _name_ _ == '_ _main_ _' 到底是什么意思?

  • 2026-08-25 02:34:03
Python 中 if _ _name_ _ == '_ _main_ _' 到底是什么意思?

Python 里 if __name__ == "__main__",真没你想得那么神秘

昨天晚上十一点多,我在公司楼下蹲着吃宵夜(真的是蹲着,凳子都被人搬走了),我们组那个小李微信上发了张截图过来,就一行:

if __name__ == "__main__":    main()

然后一句话:哥,这到底是个啥玩意?我看每个教程都这么写,就是…看不懂但大受震撼。

我一边啃鸡腿一边跟他解释,发现好多新人都对这个东西是“似懂非懂”的,要么背概念,要么只知道“入口函数要这么写”,为啥要这么干、底层到底发生了啥,反而没人说清楚。那就顺手跟你们一起捋一下。

先搞清楚:__name__ 是个啥

你就把每个 .py 文件想成一个“模块身份证”。Python 解释器加载这个模块的时候,会给它贴一个标签,塞到变量 __name__ 里。

有两种情况:

  1. 你直接运行这个文件

在命令行敲:

python demo.py

demo.py 这个文件,此刻就是“老大哥”,Python 会给它一个特别的名字:

# demo.pyprint(__name__)

直接跑一下:

python demo.py# 输出:__main__

所以:**当前这个被直接运行的模块,它的 __name__ 就是 "__main__"**。

  1. 这个文件只是被别人 import 了

再搞一个文件:

# utils.pyprint("utils 里打印 __name__:", __name__)

然后新建一个:

# app.pyimport utilsprint("app 里打印 __name__:", __name__)

命令行跑:

python app.py

你会看到类似输出:

utils 里打印 __name__: utilsapp 里打印 __name__: __main__

也就是说:

  • 被当“主文件”跑的那个,__name__ == "__main__"
  • 被 import utils 进来的那个,__name__ == "utils"(就是模块名)

到这基本能看懂那一行判断在干嘛了:就在问——我现在是被直接跑的,还是被别人当工具库引用的?

那为啥要写这么一坨 if?

你想象一个很常见的场景:写了个发短信脚本 sms_tool.py,顺手写成这样:

# sms_tool.pydefsend_marketing_sms():    print("开始给所有用户群发短信...")send_marketing_sms()

你本来只是打算 python sms_tool.py 的时候它干活。结果隔壁同事觉得你这个发短信函数写得不错,在他项目里直接:

import sms_tool

然后,呵呵了——他一启动服务,就自动给所有用户群发一遍短信…这要是在线上,基本能原地离职。

所以正常写法应该是:

# sms_tool.pydefsend_marketing_sms():    print("开始给所有用户群发短信...")if __name__ == "__main__":# 只有直接运行 sms_tool.py 时才会执行    send_marketing_sms()

这样:

  • 你自己在命令行跑这个文件,会发短信
  • 别人 import sms_tool 只是来复用 send_marketing_sms 函数,不会自动乱发

这个 if 就相当于一个“安全开关”:把“当脚本跑时要执行的逻辑”和“模块对外提供的函数/类”隔离开。

我之前写数据库压测脚本的时候也踩过类似坑,没加这玩意儿,结果一被别的工具 import,压测脚本直接在测试环境全速干活,把库打到 100%…后来才老实每个脚本都加这个判断。

再看一个最常见的套路:自测代码都塞这里

比如你写了个排序函数:

# sort_utils.pydefbubble_sort(nums):    n = len(nums)for i in range(n):for j in range(0, n - i - 1):if nums[j] > nums[j + 1]:                nums[j], nums[j + 1] = nums[j + 1], nums[j]return numsif __name__ == "__main__":# 简单自测    data = [5, 3, 1, 4, 2]    print("原始数据:", data)    print("排序结果:", bubble_sort(data))

这里有两个点:

  • 别人 from sort_utils import bubble_sort,不会看到你那些打印日志
  • 你自己 python sort_utils.py 的时候,就能当小脚本跑一跑做单元测试

很多人问“写算法题要不要建测试文件”,其实像这种简单工具类,直接在模块下面用 if __name__ == "__main__": 把测试写了就行,够用又直观。

稍微再深一点:整个项目跑起来的时候,它在哪?

比如你有个项目结构:

project/  app.py  utils.py

app.py 里写:

from utils import hellodefmain():    print("app main 里:")    hello()if __name__ == "__main__":    main()

utils.py:

defhello():    print("hello from utils, __name__ =", __name__)if __name__ == "__main__":    print("只在单独跑 utils.py 时才会出现这行")

现在你在 project 目录下敲:

python app.py

打印大概是:

app main 里:hello from utils, __name__ = utils

utils 下面那句“只在单独跑 utils.py 时才会出现这行”,不会被执行。

所以整套机制可以这么理解:

  • 整个项目真正启动的入口文件,一般就一个(比如 app.py),它会拿到 "__main__"
  • 其他所有被 import 的工具模块,都有自己正常的模块名
  • 你用这行 if,把“入口逻辑”写清楚,别人一看就知道从哪跑,维护起来也轻松

有同学会问:那我用 python -m package.module 跑包里的模块时,这个判断还准吗?

简单说一句:对你日常写业务来说,可以继续当它是准的。用 -m 跑的时候,被当入口的那个模块,也会得到 __name__ == "__main__",它下面那段代码同样会执行,其他模块照样是自己名字。内部再有一点细节,比如 __spec__ 之类的,就先别管了,你真要造框架再去研究那一层。

我现在新建 Python 文件,基本肌肉记忆就是:

defmain():# 这里随便写点要干的事passif __name__ == "__main__":    main()

哪怕暂时只是一段小脚本,这么写也有好处:

  • 以后想把脚本拆成模块的时候,不用担心 import 乱跑
  • 想给别人复用时,也不用担心一 import 就触发一堆副作用
  • 自己回头看代码,一眼就能找到“入口在哪儿”

行了,我鸡腿也啃完了,__name__ 这茬先聊到这,你要是还有那种“看了很多年但一直没搞懂”的 Python 细节,可以顺手发我一段代码截图,我有空一块给你拆开唠。

🔥私藏精品🔥
虎哥作为一名老码农,整理了全网最全《Python高级资料合集》。总量高达650GB

最新文章

随机文章