优秀的编程知识分享平台

网站首页 > 技术文章 正文

这篇if __name__ == '__main__'讲解的实在太通透了,它还能影响这些

nanyue 2025-05-26 17:49:58 技术文章 12 ℃

引言

你了解代码中为什么写 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.pyb.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.pyxxx.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 __' 将会给你省去很多麻烦。

如果这篇文章对你有帮助,点个赞让我知道哦!

Tags:

最近发表
标签列表