网站首页 > 技术文章 正文
引言
你了解代码中为什么写 if __ name __ == '__ main __' 吗?它到底是有什么用?
这篇文章除了解释 if __ name __ == '__ main __' ,还将引申一些与 if __ name __ == '__ main __' 相关的知识,例如多进程、单例、模块等等会产生的影响,如果感兴趣就继续往下读吧!
它是什么
if __ name __ == '__ main __' 代表程序的入口。
怎么样,很好理解吧!每一种程序语言都有程序入口:
C语言入口:
#include <stdio.h>
int main()
{
return 0;
}
C++入口
#include <iostream>
int main()
{
return 0;
}
JAVA入口:
public class HelloWorld {
public static void main(String[] args) {
}
}
C#入口:
using System;
namespace HelloWorldApplication
{
class HelloWorld
{
static void Main(string[] args)
{
}
}
}
上面有各种语言的程序入口示例,可以看到除了写法不同,都有一个共同点,那就是使用 main 作为入口名称。
它又不是单纯的程序入口
if __ name __ == '__ main __' 是我们 python 的程序入口,但又不是简单的程序入口。
所以接下来我将深入剖析 if __ name __ == '__ main __' ,来讲解 if __ name __ == '__ main __' 会对哪些产生影响。
原理
如果要讲到影响,我们必须要知道 if __ name __ == '__ main __' 的原理。
我们创建两个模块文件,名为 a.py 与 b.py ,他们的内容如下:
a.py
print(f'a.py {__name__}')
b.py
print(f'b.py {__name__}')
为了两个模块都进行运行,在运行某个模块时,需要引入另一个模块。
运行 a.py 模块
在 a.py 中添加 b.py 模块引入并运行:
import b
print(f'a.py {__name__}')
查看运行结果:
a.py 结果:
a.py __main__
b.py 结果:
b.py b
运行 b.py 模块
在 b.py 中添加 a.py 模块引入并运行:
import a
print(f'b.py {__name__}')
查看运行结果:
a.py 结果:
a.py a
b.py 结果:
b.py __main__
可以看到,当我们运行哪一个模块,相对模块的 __ name __ 将变为 __ main __ ,而其他模块的 __ name __ 就是其本身文件名。
所以当我们运行下面代码:
if __name__ == '__main__':
pass
其实就是当哪一个模块被调用 python xxx.py 时,那个模块文件的 __ name __ 就会变为 __ main __ 。
之后通过判断 if __ name __ == '__ main __' , 即表示被执行模块文件会执行 if 之下的代码;其他模块就算有 if __ name __ == '__ main __' 也不会执行 if 之下的代码。
各种影响
知道了原理,我们就需要来了解 if __ name __ == '__ main __' 对不同场景的影响。
1. 当前模块的影响
之前说过,python 的特性就是模块中的代码都会被执行,因此像下面的代码都会执行:
print('代码执行')
a = 1
b = 3
value = sum([a, b])
print(value)
if __name__ == '__main__':
print('这里是__main__的代码')
执行结果:
代码执行
4
这里是__main__的代码
如何避免影响
为了避免影响,最好的写法是在 if __ name __ == '__ main __' 外尽量少写会被执行的代码,而将需要执行的代码放在 if __ name __ == '__ main __' 下:
def add(a=1, b=3):
value = sum([a, b])
return value
if __name__ == '__main__':
print('代码执行')
sum_value = add(1, 3)
print(sum_value)
print('这里是__main__的代码')
2. 多模块的影响
在单模块的问题,在多个模块中也会存在,因此在多模块时,不要在模块文件中 直接编写可运行代码 ,而是使用 类、函数 进行代替。
除了运行代码影响,还有一个注意的是如果在多个文件中都存在 if __ name __ == '__ main __' ,那么只会执行 python xxx.py 中 xxx.py 的代码,例如下方:
a.py
import b
if __name__ == '__main__':
print('a.py执行')
b.py
if __name__ == '__main__':
print('b.py执行')
当我们执行 a.py 时结果如下:
a.py 结果:
a.py执行
b.py结果:没有任何输出。
如何避免影响
如果必须执行多模块中的方法,可以在其他模块创建一个 函数,然后在运行模块进行调用:
a.py
import b
if __name__ == '__main__':
print('a.py执行')
b.run()
b.py
def run():
print('b.py执行')
3. 多进程的影响
如果你不幸多进程创建在 if __ name __ == '__ main __' 之外,或者使用单例创建了在 __ init __ 中的多进程,那么你可能会得到一个无法结束,不停创建的程序了:
3.1 多进程在判断外
import time
import multiprocessing
def run():
whileTrue:
print(f'子进程')
time.sleep(1)
p = multiprocessing.Process(target=run, args=())
p.start()
if __name__ == '__main__':
print('a.py执行')
3.2 多进程在单例 __ init __
单例 b.py:
import multiprocessing
import time
class B:
_instance = None
_flag = False
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self):
ifnot B._flag:
super().__init__()
self.p = multiprocessing.Process(target=self.run, args=())
self.p.start()
B._flag = True
def run(self):
while True:
print(f'子进程方法')
time.sleep(1)
a.py 调用:
import b
b.B()
if __name__ == '__main__':
print('a.py执行')
如何避免影响
不管是多进程还是多线程,创建执行时需要在 if __ name __ == '__ main __' 之下;单例时,不要在 __ init __ 方法下创建并执行多进程或多线程。
特别说明,如果使用多进程,可以配合
multiprocessing.freeze_support() 来使用,将会省去非常多的麻烦:
if __name__ == '__main__':
multiprocessing.freeze_support()
4. 单例影响
单例影响主要是创建开销。单例如果用来长期运行某些事务而需要开启很多进程或者线程,不要在 __ init __ 中开启,而是另外添加方法开启。这个问题其实跟上面的多进程问题类似。
如何避免影响
创建开启方法,而不是在 __ init __ 中:
单例 b.py:
import multiprocessing
import time
class B:
_instance = None
_flag = False
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self):
ifnot B._flag:
super().__init__()
self.p = None
B._flag = True
def run(self):
while True:
print(f'子进程方法')
time.sleep(1)
def start(self):
ifself.p isNone:
self.p = multiprocessing.Process(target=self.run, args=())
self.p.start()
a.py 调用:
import b
import multiprocessing
if __name__ == '__main__':
multiprocessing.freeze_support()
print('a.py执行')
b.B().start()
结尾
熟练掌握 if __ name __ == '__ main __' 可以让你的程序在运行时避免不必要的开销,特别是在模块、多进程和单例使用时,运用好 if __ name __ == '__ main __' 将会给你省去很多麻烦。
如果这篇文章对你有帮助,点个赞让我知道哦!
猜你喜欢
- 2025-05-26 求职者看过来!最常见的五个面试问题如何答
- 2025-05-26 uboot-main_loop函数分析
- 2025-05-26 太阳的体检表 太阳系漫游①|观天者说
- 2025-05-26 providing/provided ( that)和if作“如果”讲的区别
- 2025-05-26 为什么要写__name__ 是 "__main__"?
- 2025-05-26 条件编译
- 2025-05-26 python学习——035python里if __name__ == "__main__"语句的作用
- 2025-05-26 常用的虚拟语气句型if it wasn't/weren't for用法解析
- 2025-05-26 btrace 开源!基于 Systrace 高性能 Trace 工具
- 2025-05-26 10道C语言笔试模拟题,你能做对几道
- 最近发表
-
- 使用这个新的 ECMAScript 运算符告别 Try/Catch!
- 抛弃 try-catch,错误处理的新方案
- 深圳尚学堂Java培训:总结java编程常用的快捷键(二)
- Try-catch speeding up my code?(speeding up)
- 能代替try catch处理异常的优雅方式
- Linux系统stress压力测试工具(linux自带的压力测试)
- ESL-通过事件控制FreeSWITCH(es事务控制)
- 谈JVM xmx, xms等内存相关参数合理性设置
- 嵌入式工程师竟然看不懂这些专业语句,那真别怪人说你菜
- 不会前端也能写官网?没问题,Devbox+Cursor 带你起飞
- 标签列表
-
- cmd/c (64)
- c++中::是什么意思 (83)
- 标签用于 (65)
- 主键只能有一个吗 (66)
- c#console.writeline不显示 (75)
- pythoncase语句 (81)
- es6includes (73)
- sqlset (64)
- windowsscripthost (67)
- apt-getinstall-y (86)
- node_modules怎么生成 (76)
- chromepost (65)
- c++int转char (75)
- static函数和普通函数 (76)
- el-date-picker开始日期早于结束日期 (70)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- & (66)
- java (73)
- js数组插入 (83)
- linux删除一个文件夹 (65)
- mac安装java (72)
- eacces (67)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)