简单而言,if __name__ == ‘__main__’ 我们简单的理解就是: 如果模块是被直接运行的,则​​if __name__ == '__main__'​​​下的代码块被运行;如果模块是被导入的,则​​if __name__ == '__main__'​​下的代码块不被运行。

下面是详细阐述:


1 程序入口

对于很多编程语言来说,程序都必须要有一个入口,比如 C,C++,以及完全面向对象的编程语言 Java等。C 和 C++ 都需要有一个 main 函数来作为程序的入口,也就是程序的运行会从 main 函数开始。

Python 则有不同,它属于脚本语言,不像编译型语言那样先将程序编译成二进制再运行,而是动态的逐行解释运行。也就是从脚本第一行开始运行,没有统一的入口

一个 Python 源码文件除了可以被直接运行外,还可以作为模块(也就是库)被导入。不管是导入还是直接运行,最顶层的代码都会被运行。而实际上在导入的时候,有一部分代码我们是不希望被运行的。

下面是一个例子,文件名为naruto.py,内容为:

pi = 3.14

def main():
print('pi:', pi)

main()

在文件里边定义了一个常量,然后又写了一个 main 函数来输出这个常量,最后运行 main 函数就相当于对定义做一遍人工检查,看看值设置的都对不对。试一试吧:直接执行该文件(naruto.py),输出:

pi: 3.14

接下来,这里有一个sasuke.py,功能是计算圆面积,该文件里边需要用到 naruto.py 文件中的pi变量,那么我们从naruto.py 中把pi变量导入到sasuke.py 中,下面是sasuke.py的内容:

from naruto import pi

def calc_round_area(r):
return pi * (r ** 2)

def main():
print("round area:", calc_round_area(2))

main()

运行sasuke.py的输出结果如下:

pi: 3.14
round area: 12.56

可以看到,naruto中的 main 函数也被运行了,实际上我们是不希望它被运行,提供 main 也只是为了对常量定义进行下测试。这时,​​if __name__ == '__main__'​​ 就派上了用场。把 naruto.py 改成下面的代码:

pi = 3.14

def main():
print('pi:', pi)

if __name__ == '__main__':
main()

将naruto.py保存后,运行sasuke.py,输出如下:

round area: 12.56

再运行naruto.py,输出如下:

pi: 3.14

这样才是我们想要的效果。

1.1 解释

​if __name__ == '__main__'​​相当于是 Python 模拟的程序入口。由于模块之间相互引用,不同模块可能都有这样的定义,而入口程序只能有一个。到底哪个入口程序被选中,这取决于 name 的值。

2 __name__

​__name__​​是内置变量,用于表示当前模块的名字,同时还能反映一个包的结构。举个例子,假设有如下一个包:

a
├── b
│ ├── c.py
│ └── __init__.py
└── __init__.py

上面的意思是说,a文件夹下有b文件夹和__init__.py。又有b文件夹下有c.py和__init__.py。

我们先在一个目录(我这里是D盘,以后都是这样,不重复说了)里新建一个文件夹命名为a,然后打开文件夹a,新建文件夹命名为b,在文件夹a中再新建一个文件命名为​​__init__.py​​​。再打开文件夹b,在文件夹b中新建两个文件​​__init__.py​​​与​​c.py​​。这三个.py文件内容都是:

print(__name__)

然后在命令行执行下面的命令:

python -c "import a.b.c"

结果为:

a
a.b
a.b.c

在这里,​​python -c​​支持执行单行命令/脚本,如:

python -c "print('Hello World!')"

输出:

Hello World!

注意:要用双引号将命令包起来,import要以​​;​​结尾,命令用[]括起来,多行命令用多个[],如;

python -c "import time;[print('Hello World!')];[print(time.time())]"

输出:

Hello World!
1602669789.738749

由此可见,​​__name__​​ 可以清晰的反映一个模块在包中的层次。

如果一个模块被直接运行,则其没有包结构,其 ​​__name__​​​值为 ​​__main__​​。

例如,在上例中,我们直接运行 c.py 文件(python a/b/c.py),输出结果如下:

__main__

所以,if name == ‘main’ 我们简单的理解就是: 如果模块是被直接运行的,则​​if __name__ == '__main__'​​​下的代码块被运行;如果模块是被导入的,则​​if __name__ == '__main__'​​下的代码块不被运行。

到这里就讨论完了​​if __name__ == '__main__'​​的作用。

3 参考文献

​​python -c 执行单行命令/脚本,有点意思​​

​Python 中的 if name == ‘main’ 该如何理解​