用python久了,对某些习以为常的东西并没有刻意深究,比如很常见的下列语句:
if __name__ == "__main__":
do_some_processing
虽然理解此if语句的意思,但并没有仔细考虑不加它的后果。最近遇到了一个类似问题,于是顺便整理了一下__name__这个变量的用法。首先它是每个module里都有的一个内置变量,且当该module被直接以命令行方式运行时 (python xx.py),它会被赋值为 "__main__";而若此module是被别的module import的时候,此变量会被赋值为该module的名字xx。
这里我直接以最简单的例子说明。首先定义一个python 文件,名为one.py:

采用 python one.py的方式运行,输出如下:

首先可以看到此脚本是从上到下顺序执行的,和JavaScript以及PHP相似,所以会依次打印上述两行语句并且可以确认__name__被赋值为字符串"__main__"。
再定义一个文件two.py, 它会import one

此时运行 python two.py,它的输出如下:

从上面输出可以再强化一下python作为脚本文件从头开始,从上而下运行的理念。第一行import one 就会导致one.py从头开始顺序运行,打印出头两行且可以确认出此时one里面的__name__被设置成了它本身的名字 one, 而不是"__main__".
上面是针对直接import one的方式,接下来是针对from one import xx的方式做类似考察,建立文件three.py。除了import语句,它和two.py非常相近:

执行命令python three.py得到如下输出:

可以发现和two的输出除了名称差别,执行顺序完全一样,仍是从头开始顺序执行。
自己的几点总结:
- Python这个从文件第一行开始执行的理念,和我们常用的C/C++/Java语言的执行方式不同,这些编译型语言执行时都会先去搜索main()入口函数,不管它位置在哪,先从它开始执行。而python/php/javascript等脚本语言则是顺序从头开始。尤其Python,有一个类似main()入口的类似语句:if __name__ == "__main__", 容易给熟悉其他语言的人造成一个“代码从这里开始执行”的误解。
- python里的 if __name__ == "__main__" 只是用来确保它的后续处理代码是在本模块 被直接运行时才执行。在下面的Flask的最简单7行代码版本,前面5行顺序执行后,就创建了Flask类对象app,并且在line 13 调用该对象的run方法来执行。
