一文弄懂Python中的 if __name__ == __main__

Posted 赵卓不凡

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一文弄懂Python中的 if __name__ == __main__相关的知识,希望对你有一定的参考价值。

1. 引言

在Python相关代码中,我们经常会遇到如下代码段:

# stuff
if __name__ == "__main__":
    # do stuff

本文将尽可能使用简单的样例来解释这里发生了什么,以及需要使用if __name__=="__main__"的情形。请注意,上述代码中namemain前后有2个下划线字符。
闲话少说,我们直接开始吧!

2. 特殊变量

当我们正常运行我们的Python脚本时,该脚本中的变量__name__的值一般为__main__。我们来看个示例:

# first.py
print(__name__)

我们在终端中运行上述脚本,代码如下:

python first.py  

输出如下:

__main__

观察上述输出,当我们运行脚本first.py的时候,变量__name__的值被设置为__main__

3. 复杂的例子

上述示例相对简单,也相对容易理解。接着我们来举个具有多个文件的例子,这里假设我们有三个脚本,分别为a.py,b.py以及c.py
其中,a.py的内容如下:

# a.py
print("__name__ in a.py:", __name__)
from b import *
from c import *

此时,b.py的内容如下:

# b.py
print("__name__ in b.py:", __name__)

c.py的内容如下:

# c.py
print("__name__ in c.py:", __name__)

如果我们运行命令python a.py得到结果如下:

__name__ in a.py: __main__
__name__ in b.py: b
__name__ in c.py: c

注意在脚本a.py中我们看到__name__的值为__main__,此时在脚本b.py__name__的值为b, 同时 c.py__name__的值为c。这是因为我们运行的脚本为a.py,那么该脚本即a.py中变量__name__的值将会被设置为字符串__main__.

此外,脚本b.pyc.py中的变量·__name__分别保持为bc,这是因为脚本b.pyc.py不是直接运行的脚本。而是我们运行的脚本a.py调用了b.pyc.py中的print函数。

如果我们单独运行python b.py得到结果如下:

__name__ in b.py: __main__

相应的我们运行python c.py,得到结果如下:

__name__ in c.py: __main__

观察上述两个输出,当我们直接运行脚本b.pyc.py,相应的脚本里的变量__name__都将被设置为__main__

4. 使用场景

作为Python开发者,我们通常会在一个项目工程中创建多个Python文件而不是将所有代码都写在一个Python文件中。因此我们通常会有一个主的Python文件用来作为项目工程的入口,同时其他文件包含一些辅助性的函数实现。
我们来看个示例,这里假设我们有两个Python文件,如下:

# main.py
from helper import *
print(greet("bob"))

辅助函数实现 helper.py内容如下:

# helper.py
def greet(name):
    return "hello " + name
print(greet("testname"))

如果此时我们运行命令 python main.py,得到结果如下:

hello bob
hello testname

主要上述的import语句将从helper.py中引入所有的语句,所以helper.py中的测试语句print(greet("testname"))也将被执行。虽然我们可以通过添加注释或者屏蔽注释来达到运行main.pyhelper.py来控制该测试语句的输出,但是这种情形就是语句
if __name__=="__main__" 大显身手的情形。

5. 解决方案

我们针对上述情形,进行代码整改,如下:

# main.py
from helper import *
print(greet("bob"))

我们修改文件 helper.py内容如下:

def greet(name):
    return "hello " + name
if __name__ == "__main__":
    print(greet("testname"))

此时,我们执行命令python main.py,得到结果如下:

hello bob

注意,此时helper.py 中的变量 __name__的值为helper, 所以helper.py中的if语句不成立,进而将不会执行我们的测试语句print(greet("testname")).

此时,如果我们单独运行命令python helper.py ,得到结果如下:

hello testname

单独运行helper.py时,此时改脚本中的变量__name__将被设置为__main__,所以此时的测试语句将会被执行,输出相应的测试结果。

6. 总结

本文重点介绍了Python中常见的if __name__=="__main__" ,重点分析了其背后的原理和应用的场景。

您学废了嘛?


关注公众号《AI算法之道》,获取更多AI算法资讯。

Python中的构造“ if __name__ == '__main__'”

【中文标题】Python中的构造“ if __name__ == \'__main__\'”【英文标题】:The construct " if __name__ == '__main__' " in PythonPython中的构造“ if __name__ == '__main__'” 【发布时间】:2015-04-04 21:00:06 【问题描述】:

我已经阅读了很多关于此的文章:

if __name__ == '__main__'

但我没听懂...我将与您分享代码。什么是更简短的解释?

我创建了一个文件,“ab.py”:

def a():
    print('A function in ab file');

a()

第二个文件是“xy.py”

import ab

def b():
    print('b function')

def x():
    print ('s');

x()

if __name__ == "__main__" :
    b()

当我执行这段代码时,就会出现这个输出:

A function in ab file
s
b function

这是什么意思?这段代码实际上在做什么?我们为什么要实施这个?我们的代码在没有它的情况下也能正常工作。

if __name__ == "__main__":
    b()

【问题讨论】:

可能重复***.com/questions/419163/what-does-if-name-main-do 我确实是从这里得到的 :( 我已经读过这个 类似于 Java 或 C# 中的 main(String[] args) What does if __name__ == "__main__": do?的可能重复 典型问题是 What does if name == "main": do?(56 个答案。7,000 次投票。6 年前。) 【参考方案1】:

理解这个语句的一个非常简单的例子如下:

假设我们有以下 Python 脚本名为:using_name.py


# Filename: using_name.py

if __name__ == '__main__':
    print 'This program is being run by itself'
else:
    print 'I am being imported from another module'

现在,尝试做以下两件事,看看会发生什么:


1) 直接运行脚本

python using_name.py

结果

This program is being run by itself

2) 导入脚本

python

import using_name

结果

I am being imported from another module

【讨论】:

这是到目前为止这个问题的最佳答案。【参考方案2】:

简单来说,if __name__ == "__main__": 中的所有内容仅在模块由 Python 解释器直接执行时运行(例如,python module.py如果在导入后显式调用函数。 p>

示例:

文件 testFile.py

# This will always be executed even if this module is simply imported by other file or this module is the entry point
print "I will always run in any situation. Even when this module is 'just' imported"

if __name__ == "__main__":
    # This will be executed only when this module is the entry point eg. python testFile.py but not if this file is imported
    print "I will only run if this module (testFile.py) is executed directly by the Python interpreter"

文件 app.py

import testFile

运行它

python testFile.py

输出

I will always run in any situation. Even when this module is 'just' imported.

I will only run if this module (file *testFile.py*) is executed directly by the Python interpreter.

运行它

python app.py

输出

I will always run in any situation. Even when this module is 'just' imported

如果您想了解__name__ 变量的内部结构: 检查What does if __name__ == "__main__": do?

【讨论】:

【参考方案3】:

这段代码实际上在做什么?

当你执行 xy.py 时,你会导入 ab。 import 语句在导入时运行模块,因此 ab 的操作在 xy 的其余部分之前执行。完成 ab 后,它会继续使用 xy

解释器跟踪使用__name__ 运行的脚本。当你运行一个脚本时——不管你给它起什么名字——解释器都称它为"__main__"。这就是它跟踪哪个脚本是主文件的方式,即在外部调用另一个脚本后返回的脚本。 (你可能会说“home”脚本。)

从此“主”脚本调用的任何其他脚本都被分配其文件名作为其__name__。因此,if __name__ == "__main__" : 行是解释器的测试,以确定它是否在它正在查看(解析)的脚本上运行,或者它是否暂时窥视另一个脚本。这使程序员可以灵活地让脚本在外部调用时表现不同。

要了解发生了什么,请首先关注未缩进的行以及它们在脚本中出现的顺序。记住这个函数——或者def——块在被调用之前不会自己做任何事情。口译员自言自语时可能会怎么想:

打开xy.py。 使用__name__ab.py导入和打开文件。 哦,一个函数。我会记住的。 好的,函数a();我刚刚学到了。我想我现在要打印了。 文件结束;回'__main__'! 哦,一个函数。我会记住的。 另一个。 函数 x();好的,打印 's'。 这是什么? if 声明。嗯,条件已经满足(变量__name__已经设置为'__main__'),所以我打印'b function'。

但是,我认为您没有正确使用它。可能有例外,但最下面两行应该是:

if __name__ == "__main__":
main()

... 这意味着“如果这是'主'或主脚本,请执行名为 main() 的函数。这就是为什么您会在顶部看到一个 def main(): 块,其中包含脚本的主要流程功能。

我们为什么要实现这个?

还记得我之前说过的关于 import 语句的内容吗?当您导入一个模块时,它不仅会“识别”它并等待进一步的说明。它实际上运行脚本中包含的所有可执行操作。因此,将脚本的内容放入 main() 函数可以有效地隔离它,将其隔离,以便在被另一个脚本导入时无法立即运行。

同样,会有例外,但通常的做法是main() 通常不会被外部调用。所以你可能想知道一件事:如果我们不调用main(),我们为什么要调用脚本呢?这是因为许多人使用独立的函数来构建他们的脚本,这些函数是为自己运行而构建的。然后在脚本正文的其他地方调用它们。这让我想到了这一点:

我们的代码在没有它的情况下也可以工作

是的,你是对的。这些单独的函数可以从不包含在main() 函数中的内嵌脚本中调用。如果您习惯于(就像我一样,在我编程的早期学习阶段)构建完全符合您需要的内联脚本,并且如果您再次需要该操作,您将尝试再次弄清楚 - 好吧,你不习惯代码的这种内部结构,因为它构建起来更复杂,而且阅读起来也不那么直观。

但这是一个可能无法在外部调用其函数的脚本,因为如果这样做,它将开始计算和分配变量。如果您尝试重用一个函数,那么您的新脚本与旧脚本的相关性可能非常密切,以至于可能存在冲突的变量。

顺便说一句,this question 包含 an answer by kindall,这最终帮助我理解了 - 为什么,而不是 如何。不幸的是,它被标记为this one 的副本,我认为这是一个错误。 (我是这个网站的新手,所以还不能标记它;如果你同意我的观点,请标记它以引起模组的进一步关注。)

【讨论】:

这似乎不是有效的 Python 代码(缩进) - (?) 好的,OP 似乎已经离开了大楼(“Last seen 1 年多前”)。【参考方案4】:

你应该养成几乎总是使用它的习惯。

if __name__ == '__main__': 之后的任何内容只有在您明确运行文件时才会运行。

python myfile.py

但是,如果您在其他地方导入 myfile.py

import myfile

if __name__ == '__main__': 下的任何内容都不会被调用。

【讨论】:

解释得很好! 非常棒的解释。 @亚当 这么简单优雅的解释!!阅读值得一读的页面,让我比以前更加困惑。这有帮助! 简单,简洁,准确的解释,我在找什么,谢谢亚当。

以上是关于一文弄懂Python中的 if __name__ == __main__的主要内容,如果未能解决你的问题,请参考以下文章

Python中的构造“ if __name__ == '__main__'”

python3----如何简单地理解Python中的if __name__ == '__main__'

如何简单理解Python中的if __name__ == '__main__':

如何简单地理解Python中的if __name__ == '__main__'

如何简单地理解Python中的if __name__ == '__main__'

如何快速简单粗暴地理解Python中的if __name__ == '__main__'