Python中的if __name__ == '__main__'(转载)
这里只是作个简单的笔记,更多精彩可阅读原作者的博客:
https://blog.csdn.net/yjk13703623757/article/details/77918633
首先感谢原作者精彩的总结和分析~~~
1前言
以前没有详解过if __name__ =='__main__'的作用,只知道当执行.py文件的时候,需要在末尾添加这行代码作为执行.py程序的入口:
if __name__ == '__main__': main()
if __name__ =='__main__'的意思是:当.py文件被直接运行的时候,if __name__ =='__main__':下方的代码将被执行;当.py文件以模块形式被导入时,if __name__ =='__main__'下代码不被执行
2 程序入口
python属于脚本语言,不像编译型语言那样先将程序编译成二进制再运行,而是动态的逐行解释运行。也就是从脚本的第一行开始运行,没有统一的入口
一个Python源码文件(.py)除了可以被直接运行外,还可以作为模块(库),被其他.py文件导入。不管是直接运行还是被导入,.py文件的最顶层代码都会被运行(python用缩进来区分代码层次)
而当一个.py文件作为模块被导入时,我们可能不希望一部分代码被运行。
2.1 一个.py文件被其他.py文件引用
假设我们有一个const.py文件:
PI = 3.14 def main(): print(“PI:”,PI) main()
area.py文件,调用const中的PI:
from const import PI def cal_round_area(radius): return PI*(radius**2) def main(): print("round area:",calc_round_area(2)) main() 运行结果: PI:3.14 round area : 12.56
2.2 修改const.py,添加if __name__=='__main__'
运行 area.py,输出:
“
round area: 12.56
”
如上,if __name__ == '__main__'相当于python模拟的程序入口,由于模块之间相互引用,不同模块可能有这样的定义,而程序入口只有一个,到底哪个程序入口被选中,取决于__name__的值。
3. __name___
3.1 __name__反映一个包的结构
__name__是内置变量,可用于反映一个包的结构,假设如下结构,a、b是文件夹目录:
在c.py、__init__.py、__init__.py的内容都为: print(__name__)
当执行导入命令:
python -c "import a.b.c"
输出结果:
a
a.b
a.b.c
由此可见,__name__可以清晰反映一个模块在包中的层次。
3.2 __name__表示当前模块的名字
__name__是内置变量,可用于表示当前模块的名字。我们直接运行一个py文件
python a/b/c.py
输出:
__main__
由此可知:如果一个py文件被直接运行时,则其没有包结构,其__name__值为__main__,即模块名为__main__
所以,if__name__== '__main__'的意思是:当py文件被直接运行时,if__name__=='__main__'之下的代码将被运行;当py文件以模块形式被导入时,if __name__=='__main__'之下的代码块不被运行。
4、__main__.py文件与python -m
Python的-m参数用于将一个模块/包作为一个脚本运行,而__main__.py相当于一个包的入口程序
4.1 运行Python程序的两种方式
直接运行xxx.py文件: python xxx.py
把xxx.py当做模块运行: python -m xxx.py
假设我们有一个文件run.py,内容如下:
import sys print(sys.path)
python run.py
输出结果:
['E:\\Pythonwork\\...\\test_name\\a',....]
python -m run.py
输出结果:
【...】
C:\ProgramData\Anaconda3\python.exe: Error while finding module specification for 'run.py' (ModuleNotFoundError: __path__ attribute not found on 'run'
结论:
- 直接运行是把run.py文件所在目录放到sys.path属性中
- 以模块方式运行是把你输入命令的目录(当前工作路径,执行run.py的时候不都是在当前目录下执行吗)放到了sys.path属性中
非run文件所在目录下执行:python -m a/run.py,会报错,no module named "a/run",“a/run”是模块名;而 python a/run.py可以成功执行
4.2 __main__.py的作用
假设包b的结构如下:
__init__的文件内容:
__main__的文件内容:
运行 python -m b结果:
运行 python b的结果:
总结:
- 当加上-m的时候,python会把当前工作目录(testname//a)添加到sys.path中;而不加-m时,python则会把脚本所在目录(具体脚本__main__和__init__所在目录b)添加到sys.path中
- 当加上 -m参数时,python会先将模块或者包导入,然后再执行(__init__用于包的导入,目录下没有__init__文件则不能作为包)
__main__.py
文件是一个包或者目录的入口程序。不管是用python b
还是用python -m b
运行,__main__.py
文件总是被执行。