1.一句话总结 if __name__ == ‘__main__’ 作用和原理
if __name__ == ‘__main__’ 是为了保护用户不在无意中(比如import)调用到脚本的主函数部分代码。
比如你在另一个脚本中导入了无 if __name__ == ‘__main__’ 保护的脚本(比如导入 test.py),那么该脚本的主函数会在导入时被触发运行,这有时会造成严重的后果。
如果你在无保护脚本中设置了一个自定义类,并将其保存在一个pickle文件中,在另一个脚本中解开它时就会触发无保护脚本的导入,其问题与上面所述的一样。
如果你看不懂这段描述,请看下面的详解:
2.详解
为了更好地理解这个问题的原因,我们需要退一步理解 Python 是如何初始化脚本的,以及这与它的模块导入机制是如何互动的。
每当 Python 解释器读取一个源文件时,它会做两件事。
- 它设置了一些特殊变量,例如
__name__
,然后 - 它执行文件中找到的所有代码。
让我们看看这是如何工作的,以及它与你关于我们在 Python 脚本中经常看到的 __name__ 检查有什么关系。
2.1 代码样例
假设代码在一个叫做foo.py的文件中。
# Suppose this is foo.py. print("before import") import math print("before functionA") def functionA(): print("Function A") print("before functionB") def functionB(): print("Function B {}".format(math.sqrt(100))) print("before __name__ guard") if __name__ == '__main__': functionA() functionB() print("after __name__ guard")
2.2 运行代码
当Python解释器读取源文件时,它首先会定义一些特殊的变量。比如__name__
虽然它长得很奇怪,前面和后面都有一个下划线_
,但是记得变量命名的规则嘛?下划线_
是可以出现在变量首字母的。所以,__name__
仍然是一个变量,只不过,是解释器自己定义的。
2.3 作为主程序运行
当我们在命令行中使用python foo.py
,或者直接在ide(比如pycharm)图形界面里点运行 foo.py,那么这时候,foo.py就是作为主程序运行的。
此时: Python解释器会直接给_name_
变量赋值为”_main_
“
2.2 作为导入的模块运行
如果有另一个程序,叫 main.py
,它里面的代码是这样的。
import foo
那么如果我们在命令行中使用 python main.py
, 则 main.py
作为主程序运行,而foo.py就是导入的模块。
此时: Python解释器会令 __name__ = "foo"
2.3 执行foo.py文件中的代码
如果使用主程序运行!python foo.py
: 输出如下:
before import before functionA before functionB before __name__ guard Function A Function B 10.0 after __name__ guard
如果使用主程序运行import foo
: 输出如下:
before import before functionA before functionB before __name__ guard after __name__ guard
可以明显看到,当使用主程序运行import foo
时,没有执行下面语句的内容,因为此时__name__ = 'foo'
if __name__ == '__main__': functionA() functionB()
3.为什么这样工作?
有时我们想编写一个.py文件,该文件既可以被其他程序和模块导入,也可以作为主程序运行。 例子如下:
- 这个文件是一个库,可以被其他文件导入。但是我们希望可以在其中运行一些单元测试或演示。
- 这个文件仅用作主程序,但具有一些单元测试的功能,一些测试框架(类似
unittest
和doctest
)需要导入这个.py
文件来测试。我们不希望,它只是因为被导入为模块,就直接运行整个脚本。 - 这个模块主要用作主程序,但它也为高级用户提供了程序员友好的
API
。
所以,其实就是有的时候希望他在被导入的时候运行一些代码,有的时候希望他作为主程序的时候运行另一些代码。所以需要进行判断。
我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。
有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。
原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!
Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典