如果__name__ == "__main__":做什么?

这有什么作用,为什么要包含if语句?

if __name__ == "__main__":print("Hello, World!")

如果你试图关闭一个应该有人使用这个习语而不是的问题,考虑关闭作为为什么当我导入我的模块时Python正在运行,以及我如何停止它?

4299810 次浏览

if __name__ == "__main__"是使用python myscript.py之类的命令从(比如说)命令行运行脚本时运行的部分。

简短回答

它是样板代码,可保护用户在无意中意外调用脚本。以下是脚本中省略保护时的一些常见问题:

  • 如果您将无保护脚本导入另一个脚本(例如import my_script_without_a_name_eq_main_guard),则后一脚本将触发前者运行在导入时使用第二个脚本的命令行参数。这几乎总是一个错误。

  • 如果您在无保护脚本中有一个自定义类并将其保存到泡菜文件中,那么在另一个脚本中解压缩它将触发无保护脚本的导入,其问题与上一个项目符号中概述的相同。

长答案

为了更好地理解为什么以及如何重要,我们需要退一步了解Python如何初始化脚本以及它如何与其模块导入机制交互。

每当Python解释器读取源文件时,它都会做两件事:

  • 它设置了一些特殊变量,例如__name__,然后

  • 它执行文件中找到的所有代码。

让我们看看这是如何工作的,以及它与您关于我们在Python脚本中经常看到的__name__检查的问题有什么关系。

代码示例

让我们使用一个略有不同的代码示例来探索导入和脚本的工作原理。

# Suppose this is foo.py.
print("before import")import math
print("before function_a")def function_a():print("Function A")
print("before function_b")def function_b():print("Function B {}".format(math.sqrt(100)))
print("before __name__ guard")if __name__ == '__main__':function_a()function_b()print("after __name__ guard")

特殊变量

当Python解释器读取源文件时,它首先定义了一些特殊变量。在这种情况下,我们关心__name__变量。

当您的模块是主程序时

如果您将模块(源文件)作为主程序运行,例如:

python foo.py

解释器将硬编码字符串"__main__"分配给__name__变量,即。

# It's as if the interpreter inserts this at the top# of your module when run as the main program.__name__ = "__main__"

当您的模块被另一个模块导入时

另一方面,假设某个其他模块是主程序并导入您的模块。这意味着主程序中有这样的语句,或者主程序导入的其他模块中有这样的语句:

# Suppose this is in some other main program.import foo

解释器将搜索您的foo.py文件(以及搜索其他一些变体),在执行该模块之前,它会将导入语句中的名称"foo"分配给__name__变量,即:

# It's as if the interpreter inserts this at the top# of your module when it's imported from another module.__name__ = "foo"

执行模块的代码

设置特殊变量后,解释器执行模块中的所有代码,一次一条语句。你可能想在代码示例旁边打开另一个窗口,这样你就可以遵循这个解释。

永远

  1. 它打印字符串"before import"(不带引号)。

  2. 它加载math模块并将其分配给一个名为math的变量。这相当于用以下内容替换import math(注意__import__是Python中的低级函数,它接受一个字符串并触发实际导入):

# Find and load a module given its string name, "math",# then assign it to a local variable called math.math = __import__("math")
  1. 它打印字符串"before function_a"

  2. 它执行def块,创建一个函数对象,然后将该函数对象分配给一个名为function_a的变量。

  3. 它打印字符串"before function_b"

  4. 它执行第二个def块,创建另一个函数对象,然后将其分配给一个名为function_b的变量。

  5. 它打印字符串"before __name__ guard"

只有当您的模块是主程序时

  1. 如果您的模块是主程序,那么它将看到__name__确实设置为"__main__"并调用这两个函数,打印字符串"Function A""Function B 10.0"

只有当您的模块被另一个模块导入时

  1. 而是)如果你的模块不是主程序,而是被另一个程序导入的,那么__name__将是"foo",而不是"__main__",它将跳过if语句的主体。

永远

  1. 在这两种情况下,它都将打印字符串"after __name__ guard"

总结

总之,这是两个案例中打印的内容:

# What gets printed if foo is the main programbefore importbefore function_abefore function_bbefore __name__ guardFunction AFunction B 10.0after __name__ guard
# What gets printed if foo is imported as a regular modulebefore importbefore function_abefore function_bbefore __name__ guardafter __name__ guard

为什么它以这种方式工作?

你可能很自然地想知道为什么有人会想要这个。嗯,有时你想写一个.py文件,它既可以被其他程序和/或模块用作模块,也可以作为主程序本身运行。例子:

  • 您的模块是一个库,但您希望有一个脚本模式,它可以在其中运行一些单元测试或演示。

  • 您的模块仅用作主程序,但它有一些单元测试,测试框架通过导入.py文件(如您的脚本)并运行特殊的测试函数来工作。您不希望它仅仅因为正在导入模块而尝试运行脚本。

  • 您的模块主要用作主程序,但它也为高级用户提供了一个程序员友好的API。

除了这些例子之外,在Python中运行脚本只是设置一些神奇的变量并导入脚本,“运行”脚本是导入脚本模块的副作用。

思考的食物

  • 问题:我可以有多个__name__检查块吗?答案:这样做很奇怪,但语言不会阻止你。

  • 假设以下内容在foo2.py中。如果您在命令行上说python foo2.py会发生什么?为什么?

# Suppose this is foo2.py.import os, sys; sys.path.insert(0, os.path.dirname(__file__)) # needed for some interpreters
def function_a():print("a1")from foo2 import function_bprint("a2")function_b()print("a3")
def function_b():print("b")
print("t1")if __name__ == "__main__":print("m1")function_a()print("m2")print("t2")      
  • 现在,弄清楚如果删除foo3.py中的__name__签入会发生什么:
# Suppose this is foo3.py.import os, sys; sys.path.insert(0, os.path.dirname(__file__)) # needed for some interpreters
def function_a():print("a1")from foo3 import function_bprint("a2")function_b()print("a3")
def function_b():print("b")
print("t1")print("m1")function_a()print("m2")print("t2")
  • 当作为脚本使用时,这会做什么?当作为模块导入时?
# Suppose this is in foo4.py__name__ = "__main__"
def bar():print("bar")    
print("before __name__ guard")if __name__ == "__main__":bar()print("after __name__ guard")

当您的脚本通过将其作为命令传递给Python解释器来运行时,

python myscript.py

所有缩进级别为0的代码都会被执行。定义的函数和类都被定义了,但是它们的代码都没有运行。与其他语言不同,没有main()函数会自动运行-main()函数隐含地是顶层的所有代码。

在这种情况下,顶层代码是if块。__name__是一个内置变量,计算结果为当前模块的名称。但是,如果一个模块直接运行(如上面的myscript.py),那么__name__将被设置为字符串"__main__"。因此,您可以通过测试来测试您的脚本是直接运行还是被其他东西导入

if __name__ == "__main__":...

如果你的脚本被导入到另一个模块中,它的各种函数和类定义将被导入,它的顶级代码将被执行,但是上面if子句的then-body中的代码不会运行,因为条件不满足。作为一个基本的例子,考虑以下两个脚本:

# file one.pydef func():print("func() in one.py")
print("top-level in one.py")
if __name__ == "__main__":print("one.py is being run directly")else:print("one.py is being imported into another module")
# file two.pyimport one
print("top-level in two.py")one.func()
if __name__ == "__main__":print("two.py is being run directly")else:print("two.py is being imported into another module")

现在,如果您调用解释器作为

python one.py

输出将是

top-level in one.pyone.py is being run directly

如果你运行two.py

python two.py

你得到

top-level in one.pyone.py is being imported into another moduletop-level in two.pyfunc() in one.pytwo.py is being run directly

因此,当模块one被加载时,它的__name__等于"one"而不是"__main__"

创建以下两个文件:

# a.py
import b
# b.py
print("__name__ equals " + __name__)
if __name__ == '__main__':print("if-statement was executed")

现在单独运行每个文件。


运行python a.py

$ python a.py__name__ equals b

a.py执行时,它导入模块b。这导致b中的所有代码运行。Python将b模块中的globals()['__name__']设置为模块的名称b


运行python b.py

$ python b.py__name__ equals __main__if-statement was executed

当只执行文件b.py时,Python将此文件中的globals()['__name__']设置为"__main__"。因此,if语句这次的计算结果为True

它是从命令行调用Python文件时的特殊用途。这通常用于调用“main()”函数或执行其他适当的启动代码,例如命令行参数处理。

它可以用几种方式写成。另一种是:

def some_function_for_instance_main():dosomething()

__name__ == '__main__' and some_function_for_instance_main()

我不是说你应该在生产代码中使用它,但它可以说明if __name__ == '__main__'没有什么“神奇”的。

它只是在Python文件中调用main函数的约定。

当我们的模块(M.py)中存在某些语句时,我们希望在它作为main(而不是导入)运行时执行,我们可以将这些语句(测试用例、打印语句)放在这个if块下。

默认情况下(当模块作为main运行时,不导入)__name__变量设置为"__main__",当它被导入时,__name__变量将获得不同的值,很可能是模块的名称('M')。这有助于一起运行模块的不同变体,并分离它们的特定输入和输出语句,以及是否有任何测试用例。

总之,使用这个“if __name__ == "main"”块来防止(某些)代码在导入模块时运行。

if __name__ == "__main__":是做什么的?

概述基础知识:

  • 在作为程序切入点的模块中,全局变量__name__'__main__'。否则,它是您导入模块的名称。

  • 因此,只有当模块是程序的切入点时,if块下的代码才会运行。

  • 它允许模块中的代码可以被其他模块导入,而无需在导入时执行下面的代码块。


我们为什么需要这个?

开发和测试您的代码

假设您正在编写一个旨在用作模块的Python脚本:

def do_important():"""This function does something very important"""

可以通过将函数的此调用添加到底部来测试模块:

do_important()

并运行它(在命令提示符下),如下所示:

~$ python important.py

问题

但是,如果您想将模块导入另一个脚本:

import important

在导入时,将调用do_important函数,因此您可能会在底部注释掉您的函数调用do_important()

# do_important() # I must remember to uncomment to execute this!

然后你必须记住你是否已经注释掉你的测试函数调用。而这种额外的复杂性意味着你可能会忘记,使你的开发过程更加麻烦。

更好的方法

__name__变量指向Python解释器当前所在的命名空间。

在导入的模块中,它是该模块的名称。

但是在主模块(或交互式Python会话,即解释器的Read、Eval、print Loop或REPL)中,您正在运行其"__main__"中的所有内容。

因此,如果您在执行之前检查:

if __name__ == "__main__":do_important()

有了上面的内容,您的代码只会在您将其作为主模块运行(或有意从另一个脚本调用它)时执行。

一个更好的方法

不过,有一种Pythonic方法可以改进这一点。

如果我们想从模块外部运行这个业务流程怎么办?

如果我们把我们想在开发和测试时练习的代码放在这样的函数中,然后在下面立即检查'__main__'

def main():"""business logic for when running this module as the primary one!"""setup()foo = do_important()bar = do_even_more_important(foo)for baz in bar:do_super_important(baz)teardown()
# Here's our payoff idiom!if __name__ == '__main__':main()

我们现在有一个用于模块末尾的最终函数,如果我们将模块作为主模块运行,该函数将运行。

它将允许模块及其函数和类在不运行main函数的情况下导入到其他脚本中,并且还将允许在从不同的'__main__'模块运行时调用模块(及其函数和类),即:

import importantimportant.main()

这个习惯用法也可以在Python留档#0模块的解释中找到。该文本指出:

此模块表示(否则是匿名的)范围,其中解释器的主程序执行-命令从标准输入,来自脚本文件或交互式提示符。它在这个环境中,惯用的“条件脚本”节导致脚本运行:

if __name__ == '__main__':main()

当您以交互方式运行Python时,本地__name__变量的值为__main__。同样,当您从命令行执行Python模块时,而不是将其导入另一个模块时,其__name__属性的值为__main__,而不是模块的实际名称。通过这种方式,模块可以查看自己的__name__值以自行确定它们是如何被使用的,无论是作为对另一个程序的支持还是作为从命令行执行的主应用程序。因此,以下习语在Python模块中很常见:

if __name__ == '__main__':# Do something appropriate here, like calling a# main() function defined elsewhere in this module.main()else:# Do nothing. This module has been imported by another# module that wants to make use of the functions,# classes and other useful bits it has defined.

if __name__ == "__main__":能做什么?

__name__是存在于所有命名空间中的全局变量(在Python中,global实际上意味着在模块级上)。它通常是模块的名称(作为str类型)。

然而,作为唯一的特例,在您运行的任何Python进程中,如mycode.py:

python mycode.py

否则匿名的全局命名空间将'__main__'的值分配给其__name__

因此,包括的最后一行

if __name__ == '__main__':main()
  • 在你mycode.py剧本的结尾,
  • 当它是由Python进程运行的主要入口点模块时,

将导致脚本唯一定义的main函数运行。

使用此构造的另一个好处:您还可以将代码作为另一个脚本中的模块导入,然后在您的程序决定时运行main函数:

import mycode# ... any amount of other codemycode.main()

让我们以更抽象的方式来看看答案:

假设我们在x.py中有这段代码:

...<Block A>if __name__ == '__main__':<Block B>...

块A和B在我们运行x.py时运行。

但是当我们运行另一个模块时,只是块A(而不是B)运行,例如y.py,其中x.py被导入并从那里运行代码(就像从y.py调用x.py中的函数时)。

系统(Python解释器)为源文件(模块)提供了许多变量。您可以随时获取它们的值,所以,让我们关注__name__变量/属性:

当Python加载源代码文件时,它会执行其中找到的所有代码。(请注意,它不会调用文件中定义的所有方法和函数,但它确实定义了它们。)

在解释器执行源代码文件之前,它为该文件定义了一些特殊变量;__name__是Python为每个源代码文件自动定义的特殊变量之一。

如果Python将此源代码文件加载为主程序(即您运行的文件),则它会将此文件的特殊__name__变量设置为值“__main__”

如果这是从另一个模块导入的,__name__将设置为该模块的名称。

所以,在你的例子中:

if __name__ == "__main__":lock = thread.allocate_lock()thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))

意味着代码块:

lock = thread.allocate_lock()thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))

只有当您直接运行模块时才会执行;如果另一个模块正在调用/导入它,代码块将不会执行,因为在该特定实例中__name__的值不等于“主要”。

希望这能有所帮助。

if __name__ == "__main__":基本上是顶级脚本环境,它指定解释器(“我有最高优先级要首先执行”)。

'__main__'是执行顶级代码的作用域的名称。当从标准输入、脚本或交互式提示符读取模块时,模块的__name__设置为'__main__'

if __name__ == "__main__":# Execute only if run as a scriptmain()

考虑:

print __name__

上面的输出是__main__

if __name__ == "__main__":print "direct method"

上面的语句是true并打印“直接法”。假设他们在另一个类中导入了这个类,它不会打印“直接法”,因为在导入时,它会设置__name__ equal to "first model name"

关于所讨论的代码机制,这里有很多不同的看法,“如何”,但对我来说,在我理解“为什么”之前,这些都没有意义。这对新程序员应该特别有帮助。

取文件“ab.py”:

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

第二个文件“xy.py”:

import abdef main():print('main function: this is where the action is')def x():print ('peripheral task: might be useful in other projects')x()if __name__ == "__main__":main()

这段代码到底在做什么?

当你执行xy.py时,你就是import ab。导入语句在导入时立即运行模块,因此ab的操作在xy的其余操作之前执行。完成ab后,它继续xy

解释器跟踪使用__name__运行的脚本。当您运行脚本时-无论您将其命名为什么-解释器都会将其称为"__main__",使其成为运行外部脚本后返回的主脚本或“主”脚本。

从这个"__main__"脚本调用的任何其他脚本都会将其文件名分配为其__name__(例如__name__ == "ab.py")。因此,第3行是解释器的测试,以确定它是在解释/解析最初执行的“home”脚本,还是暂时查看另一个(外部)脚本。这使程序员可以灵活地让脚本在直接执行和外部调用时表现不同。

让我们逐步通过上面的代码来理解发生了什么,首先关注未缩进的行以及它们在脚本中出现的顺序。请记住,函数-或def-块在被调用之前不会自己做任何事情。如果解释器自言自语,可能会说:

  • 打开xy.py作为“home”文件;在__name__变量中调用它"__main__"
  • 使用__name__ == "ab.py"导入并打开文件。
  • 哦,一个功能。我会记住的。
  • 好的,函数a();我刚刚学会了。打印'ab文件中的一个函数'。
  • 文件结束;回到"__main__"
  • 哦,一个功能。我会记住的。
  • 另一个。
  • 函数x();好的,打印“外围任务:可能对其他项目有用”。
  • 这是什么?if语句。好吧,条件已经满足(变量__name__已设置为"__main__"),所以我将输入main()函数并打印'主要功能:这是动作所在'。

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

为什么要实施这个?

还记得我之前说过的导入语句吗?当你导入一个模块时,它不仅仅是“识别”它并等待进一步的指令——它实际上运行脚本中包含的所有可执行操作。因此,将脚本的内容放入main()函数有效地隔离了它,将其隔离,这样当它被另一个脚本导入时就不会立即运行。

同样,也会有例外,但通常的做法是main()通常不会被外部调用。所以你可能会想另一件事:如果我们不调用main(),为什么我们要调用脚本?这是因为许多人用独立的函数构建他们的脚本,这些函数的运行独立于文件中的其余代码。然后他们后来在脚本主体的其他地方被调用。这让我想到了这一点:

但没有它代码也能工作

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

但这是一个可能无法从外部调用其函数的脚本,因为如果它这样做了,它会立即开始计算和分配变量。如果你试图重用一个函数,你的新脚本很可能与旧脚本关系密切,会有冲突的变量。

在拆分独立函数时,您可以通过将它们调用到另一个脚本中来重用以前的工作。例如,“example.py”可能会导入“xy.py”并调用x(),利用“xy.py”中的“x”函数。(也许它是将给定文本字符串的第三个单词大写;从数字列表创建NumPy数组并对它们进行平方;或者消除3D表面。可能性是无限的。)

(顺便说一句,这个问题中包含了一个@kinall的答案,它最终帮助我理解了为什么,而不是如何。不幸的是,它被标记为这一个的副本,我认为这是一个错误。)

简单地说,__name__是为每个脚本定义的变量,它定义了脚本是作为主模块运行还是作为导入模块运行。

所以如果我们有两个脚本;

#script1.pyprint "Script 1's name: {}".format(__name__)

#script2.pyimport script1print "Script 2's name: {}".format(__name__)

执行script1的输出是

Script 1's name: __main__

执行script2的输出是:

Script1's name is script1Script 2's name: __main__

如您所见,__name__告诉我们哪个代码是“main”模块。这很棒,因为你可以只编写代码,而不必担心像C/C++这样的结构问题,如果一个文件没有实现“main”函数,那么它就不能编译为可执行文件,如果它实现了,它就不能用作库。

假设你写了一个Python脚本,它做了一些很棒的事情,并且你实现了一大堆对其他目的有用的函数。如果我想使用它们,我可以导入你的脚本并使用它们而不执行你的程序(假设你的代码只在if __name__ == "__main__":上下文中执行)。而在C/C++中,你必须将这些片段分成一个单独的模块,然后包含文件。想象一下下面的情况;

C中的复杂导入

箭头是导入链接。对于三个模块,每个模块都试图包含前面的模块代码,有六个文件(九个,计算实现文件)和五个链接。这使得很难将其他代码包含到C项目中,除非它是专门作为库编译的。现在为Python想象一下:

在Python中优雅的导入

您编写一个模块,如果有人想使用您的代码,他们只需导入它,__name__变量可以帮助将程序的可执行部分与库部分分开。

我认为最好用深入和简单的语言来打破答案:

__name__:Python中的每个模块都有一个名为__name__的特殊属性。它是一个内置变量,返回模块的名称。

__main__:与其他编程语言一样,Python也有一个执行切入点,即main。'__main__'是执行顶级代码的范围的名称。基本上,您有两种使用Python模块的方式:直接将其作为脚本运行,或导入它。当模块作为脚本运行时,其__name__设置为__main__

因此,当模块作为主程序运行时,__name__属性的值设置为__main__。否则,__name__的值设置为包含模块的名称。

您可以使文件可用作脚本可导入模块

fibo.py(名为fibo的模块)

# Other modules can IMPORT this MODULE to use the function fibdef fib(n):    # write Fibonacci series up to na, b = 0, 1while b < n:print(b, end=' ')a, b = b, a+bprint()
# This allows the file to be used as a SCRIPTif __name__ == "__main__":import sysfib(int(sys.argv[1]))

参考:https://docs.python.org/3.5/tutorial/modules.html

考虑:

if __name__ == "__main__":main()

它检查Python脚本的__name__属性是否为"__main__"。换句话说,如果程序本身被执行,属性将为__main__,因此程序将被执行(在本例中为main()函数)。

但是,如果您的Python脚本由模块使用,则将执行if语句之外的任何代码,因此if __name__ == "__main__"仅用于检查程序是否用作模块,从而决定是否运行代码。

的原因

if __name__ == "__main__":main()

主要是为了避免直接导入代码出现的导入锁问题。如果您的文件是直接调用的(这是__name__ == "__main__"的情况),您希望main()运行,但如果您的代码是导入的,那么导入器必须从真正的main模块输入您的代码以避免导入锁定问题。

一个副作用是你自动登录到一个支持多个入口点的方法论。你可以使用main()作为切入点,但你没必要这么做来运行你的程序。虽然setup.py期望main(),但其他工具使用替代入口点。例如,要将文件作为gunicorn进程运行,你定义了一个app()函数而不是main()。就像setup.py一样,gunicorn导入你的代码,所以你不希望它在导入时做任何事情(因为导入锁问题)。

创建一个文件,a.py

print(__name__) # It will print out __main__

__name__总是等于__main__,只要该文件是直接运行,表明这是主文件。

在同一目录中创建另一个文件b.py

import a  # Prints a

运行它。它将打印一个,即是进口的文件名。

所以,为了显示同一文件的两种不同行为,这是一个常用的技巧:

# Code to be run when imported into another python file
if __name__ == '__main__':# Code to be run only when run directly

在解释任何关于if __name__ == '__main__'的事情之前,重要的是要了解__name__是什么以及它的作用。

什么是__name__

__name__是一个DunderAlias-可以被认为是一个全局变量(可从模块访问),其工作方式与#1类似。

它是一个字符串(如上所述的全局),如type(__name__)(产生<class 'str'>)所示,并且是python3python2版本的内置标准。

哪里

它不仅可以在脚本中使用,还可以在解释器和模块/包中找到。

口译员:

>>> print(__name__)__main__>>>

脚本:

test_file.py

print(__name__)

导致__main__

模块或包:

somefile.py:

def somefunction():print(__name__)

test_file.py:

import somefilesomefile.somefunction()

导致somefile

请注意,当在包或模块中使用时,__name__采用文件的名称。实际模块或包路径的路径没有给出,但有自己的DunderAlias__file__,允许这样做。

您应该看到,其中__name__,它是主文件(或程序)将总是返回__main__,如果它是一个模块/包,或任何运行其他Python脚本的东西,将返回它起源的文件的名称。

实践

作为一个变量意味着它的值可以被覆盖(“可以”并不意味着“应该”),覆盖__name__的值将导致缺乏易读性。所以不要这样做,无论如何。如果你需要一个变量,定义一个新变量。

总是假设__name__的值是__main__或文件名。再次更改此默认值会引起更多混淆,认为它会有好处,从而导致进一步的问题。

示例:

>>> __name__ = 'Horrify' # Change default from __main__>>> if __name__ == 'Horrify': print(__name__)...>>> else: print('Not Horrify')...Horrify>>>

在脚本中包含if __name__ == '__main__'通常被认为是良好的做法。

现在回答if __name__ == '__main__'

现在我们知道__name__的行为变得更加清晰:

#0是一个流控制语句,它包含如果给定的值为true将执行的代码块。我们已经看到__name__可以接受__main__或导入的文件名。

这意味着如果__name__等于__main__,则该文件必须是主文件并且必须实际运行(或者它是解释器),而不是导入脚本的模块或包。

如果__name__确实取了__main__的值,那么该代码块中的任何内容都将执行。

这告诉我们,如果正在运行的文件是主文件(或者您直接从解释器运行),则必须执行该条件。如果它是一个包,那么它不应该,并且值不会是__main__

模块

__name__也可以在模块中用于定义模块的名称

变式

也可以用__name__做其他不太常见但有用的事情,我将在这里展示一些:

仅当文件是模块或包时执行

if __name__ != '__main__':# Do some useful things

如果文件是主文件,则运行一个条件,如果不是,则运行另一个条件

if __name__ == '__main__':# Execute somethingelse:# Do some useful things

您还可以使用它在包和模块上提供可运行的帮助函数/实用程序,而无需精心使用库。

它还允许模块作为主脚本从命令行运行,这也非常有用。

我们经常看到__name__ == '__main__':

它检查模块是否正在导入。

换句话说,只有当代码直接运行时,if块中的代码才会被执行。这里directly意味着not imported

让我们看看它使用打印模块名称的简单代码做了什么:

# test.pydef test():print('test module name=%s' %(__name__))
if __name__ == '__main__':print('call test()')test()

如果我们直接通过python test.py运行代码,则模块名称为__main__

call test()test module name=__main__

所有的答案几乎都解释了它的功能。但我将提供一个使用示例,这可能有助于进一步澄清这个概念。

假设您有两个Python文件,a.py和b.py.现在,a.py导入b.py.我们运行a.py文件,其中首先执行“导入b.py”代码。在其余a.py代码运行之前,文件b.py中的代码必须完全运行。

在b.py代码中,有一些代码是该文件独有的b.py我们不希望导入b.py文件的任何其他文件(b.py文件除外)运行它。

这就是这行代码检查的内容。如果是主文件(即b.py)运行代码,在这种情况下不是(a.py是主文件运行),那么只有代码被执行。

如果这个. py文件被其他. py文件导入,if语句下的代码将不会被执行。

如果这个. py由shell下的python this_py.py运行,或者在Windows中双击。if语句下的代码将被执行。

它通常用于测试。

简而言之,你需要知道几点:

  1. import a操作实际上运行了a.py中可以运行的所有操作,这意味着a.py中的每一行

  2. 由于第1点,您可能不希望导入时所有内容都在a.py中运行

  3. 为了解决第2点中的问题,Python允许您使用条件检查

  4. __name__是所有.py模块中的隐式变量:

  • a.pyimported时,a.py模块__name__的值设置为其文件名“a
  • a.py直接使用“python a.py”运行时,__name__的值设置为字符串__main__
  1. 基于Python如何为每个模块设置变量__name__的机制,你知道如何实现第3点吗?答案相当简单,对吧?使用如果条件:if __name__ == "__main__": // do A
  • 然后python a.py将运行部分// do A
  • import a将跳过部分// do A
  1. 您甚至可以根据您的功能需要放置if__name__ == "a",但很少这样做

Python的特别之处在于第4点!其余的只是基本逻辑。

我一直在阅读这一页上的答案。我想说,如果你知道答案,你肯定会理解这些答案,否则,你仍然很困惑。

此答案适用于学习Python的Java程序员。每个Java文件通常包含一个公共类。您可以通过两种方式使用该类:

  1. 从其他文件调用类。您只需将其导入调用程序即可。

  2. 单独运行类,用于测试目的。

对于后一种情况,类应该包含一个公共静态无效main()方法。在Python中,此目的由全局定义的标签'__main__'提供。

简单地说,它是运行文件的切入点,就像C编程语言中的main函数一样。

Python中的每个模块都有一个名为__name__的属性。当模块直接运行时,__name__属性的值是__main__,就像python my_module.py。否则(就像你说import my_module时)__name__的值是模块的名称。

举个小例子,简而言之。

脚本test.py

apple = 42
def hello_world():print("I am inside hello_world")
if __name__ == "__main__":print("Value of __name__ is: ", __name__)print("Going to call hello_world")hello_world()

我们可以直接执行这个作为

python test.py

产出

Value of __name__ is: __main__Going to call hello_worldI am inside hello_world

现在假设我们从另一个脚本调用上面的脚本:

脚本external_calling.py

import test
print(test.apple)test.hello_world()
print(test.__name__)

当你执行这个时,

python external_calling.py

产出

42I am inside hello_worldtest

所以,上面是不言自明的,当你从另一个脚本调用测试时,如果test.py中的循环__name__将不会执行。

如果Python解释器正在运行一个特定的模块,那么__name__全局变量的值将为"__main__"

  def a():print("a")
def b():print("b")
if __name__ == "__main__":
print ("you can see me")a()else:
print ("You can't see me")b()

当您运行此脚本时,它会打印你能看见我

一个

如果您导入此文件,将A说成文件B,并执行文件B,则文件A中的if __name__ == "__main__"变为false,因此它打印你看不见我

b

您可以使用这个简单的示例检查特殊变量__name__

创建file1.py

if __name__ == "__main__":print("file1 is being run directly")else:print("file1 is being imported")

创建*file2.py

import file1 as f1
print("__name__ from file1: {}".format(f1.__name__))print("__name__ from file2: {}".format(__name__))
if __name__ == "__main__":print("file2 is being run directly")else:print("file2 is being imported")

执行file2.py

产出

file1 is being imported__name__ from file1: file1__name__ from file2: __main__file2 is being run directly

如果模块作为脚本调用,if __name__ == '__main__':下的代码将只有执行。

例如,考虑以下模块my_test_module.py

# my_test_module.py
print('This is going to be printed out, no matter what')
if __name__ == '__main__':print('This is going to be printed out, only if user invokes the module as a script')

第一种可能:在另一个模块中导入my_test_module.py

# main.py
import my_test_module
if __name__ == '__main__':print('Hello from main.py')

现在如果你调用main.py

python main.py
>> 'This is going to be printed out, no matter what'>> 'Hello from main.py'

请注意,仅执行my_test_module中的顶级print()语句。


第二种可能:调用my_test_module.py作为脚本

现在,如果您将my_test_module.py作为Python脚本运行,则将执行print()语句:

python my_test_module.py
>>> 'This is going to be printed out, no matter what'>>> 'This is going to be printed out, only if user invokes the module as a script'

更全面的解释,你可以阅读#0在Python中做什么

python main函数是任何程序的起点。当程序运行时,Python解释器按顺序运行代码。main函数仅在作为Python程序运行时执行…

def main():print("I am in the function")
print("I am out of the function")

当您运行脚本时,会显示:

I am out of the function

而不是代码“我在函数中”。

这是因为我们没有声明调用函数“if__name__==”主要“。

如果你使用它:

def main():print("I am in the function")
if __name__ == "__main__":main()
print("I am out of the function")

输出等于

I am in the functionI am out of the function

在Python中,if__name__== "__main__"允许您将Python文件作为可重用模块或独立程序运行。

当Python解释器读取源文件时,它将执行其中找到的所有代码。当Python将“源文件”作为主程序运行时,它将特殊变量__name__设置为值"__main__"

当您执行main函数时,它将读取if语句,该语句检查__name__是否等于__main__

Python中的每个模块都有一个名为__name__的特殊属性。当模块作为主程序执行时(例如,运行python foo.py),__name__属性的值设置为'__main__'

否则,__name__的值将设置为调用它的模块的名称。

简单的一句话:

您在if __name__ == "__main__":下看到的代码只会在您的Python文件作为python example1.py执行时被调用

但是,如果您希望将Python文件example1.py作为模块导入以处理另一个Python文件,例如example2.py,则if __name__ == "__main__":下的代码将不会运行或产生任何效果。

if __name__ == "__main__"意味着如果您像python foo.py一样正常运行Python文件,它会将特殊变量__name__分配给"__main__"

但是,如果您导入的是像“导入foo”这样的文件,它会将__name__分配给"foo",并且不会运行该函数。

当执行Python文件时,它会创建许多特殊变量,例如__name__。变量__name__保存文件的名称。你问题的答案是

if __name__ == "__main__":# Do something

这意味着如果正在执行的文件的名称作为源文件和不是模块运行,那么它将运行其中的代码。这可以用一个简单的例子来证明。创建两个Python文件,foo.pysecond.py。然后在foo.py中,键入以下内容:

if __name__ == "__main__":print("file is not imported")else:print("file is imported")

second.py中,键入:

import foo
if foo.__name__ == "__main__":print("file is not imported")else:print("file is imported")

除此之外,如果您执行此print(__name__),那么它将打印__main__。为什么?

因为该文件是作为主要源运行的,如果您执行print(foo.__name__),它将打印foo,因为__name__变量的默认值是文件的名称,默认情况下我的意思是您也可以更改它。要做到这一点,只需转到foo.py文件并执行此操作:__name__ = "name"。然后当您运行该文件时,例如,

__name__ = "Hello, World!"print(__name__)

那么输出将是:

Hello, World!

当您执行模块(源文件)时,如果条件检查模块是直接调用还是从另一个源文件调用。这里直接意味着未导入。

如果直接调用执行,则模块名称设置为“main”,然后将执行如果块内的代码。

假设我在维基百科上为网络抓取编写了函数和类。当然,这可能不是一个好例子。

我想在另一个程序中使用这些函数而不重写它。

好吧,我导入它们,但在该文件的末尾我把__name__ == '__main__'

当我们import一个模块时,它里面的所有代码从头到尾执行。但当它达到条件时,它不运行func功能2等,这就是维基百科__scrape__

好吧,在全局范围内,对于当前程序,Python__name__被定义为'__main__'

当我们import一个模块时,它被定义为当前程序名称空间中的变量当前程序__name__'__main__'

文件test.py

def func():# Do somethingpass
def func2():# Do somethingpass
print('The program name is set to ', globals()['__name__'])
if __name__=='__main__':# In the current program, __name__ is equal to '__main__'func('https://www.wikipedia.org')func2('https://www.wikipedia.org')# Or do more jobs
import test1print('inside of current program')print('name is current program', __name__)print(globals()['test1'])test1.func('another site')test1.func2('another site')

产出

inside of test 1name of program is set to test1end of moduleinside of current__main__<module 'test1' from 'C:\\users\\ir\\appdata\\local\\programs\\python\\python38\\lib\\test1.py'>

如果您是初学者,可能您现在需要的唯一答案是简单脚本的此代码是不必要的。只有当您希望能够对脚本进行import(或unpickle等;请参阅此处的其他答案以了解其他一些非初学者场景)时,它才有用。

换句话说,if __name__守卫是一种从其他代码中隐藏代码的机制。如果你没有特定的理由隐藏某些东西,不要:如果你不需要从import隐藏某些代码,不要把它放在这个守卫后面,如果你这样做了,尽可能少地隐藏。

更详细地说,假设您有一个简单的脚本fib.py(改编自这个答案):

# XXX FIXME: useless (see below)if __name__ == "__main__":n = int(input('Write a number: '))a, b = 0, 1while b < n:a, b = b, a+bprint('Fibonacci number %i: %i' % (n, b))

现在,如果你只是运行python fib.py,它就可以正常工作。但是在这种情况下,__name__将永远是"__main__",所以这个条件实际上是不必要的。脚本可以简化为

n = int(input('Write a number: '))a, b = 0, 1while b < n:a, b = b, a+bprint('Fibonacci number %i: %i' % (n, b))

现在,你不能用新版本import fib,但如果你一开始就不打算这样做,这个版本实际上更好,因为它更简单,更清晰。

如果你希望能够import fib,那么第一个版本也是无用的,因为有用的代码在你import这个文件时不会运行的部分(在这种情况下__name__不会是"__main__")。在这种情况下,正确的设计是重构代码,以便有用的部分在你import之后可以在你想运行的时候运行它。

def main():n = int(input('Write a number: '))a, b = 0, 1while b < n:a, b = b, a+bprint('Fibonacci number %i: %i' % (n, b))
if __name__ == "__main__":main()

现在,如果您import fib,则不会执行对main()的调用;但当您运行python fib.py时,它会执行。

实际上,更好的设计仍然是将可重用部分(实际计算)与用户可见的输入/输出隔离开来:

def fibn(n: int) -> int:a, b = 0, 1while b < n:a, b = b, a+breturn b
def main() -> None:n = int(input('Write a number: '))print('Fibonacci number %i: %i' % (n, fibn(n)))
if __name__ == "__main__":main()

现在,您可以from fib import fibn并从执行此import的代码中调用fibn()函数。

(我调用函数fibn()只是为了更清楚地说明这个例子中的内容。在现实生活中,您可能会调用它fib()并执行from fib import fib。)

类似地,如果您想重用它,您可以import并调用main函数。

回到问题中的代码,我同样会将代码从if移动到一个函数中,以便调用者可以在需要时调用该函数。

def main():lock = thread.allocate_lock()thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))
if __name__ == "__main__":main()

这改变了lock变量的作用域;如果周围的代码需要访问它,您需要将其设置为global(或者,更好的是,将main重构为return lock,并让调用者在自己的局部变量中捕获值)。

(与C等语言不同,名称main对Python没有特定的含义;但使用它作为将要运行的东西的名称是一种常见的约定。你仍然必须真正明确地调用它,就像main(),不像C。)

简单的答案是,如果您将其导入另一个文件,那么在如果name=="main":下编写的代码将不会执行。

只有你需要知道的事实

这个问题的其他答案太长了。实际的机制非常简单,只有两个基本事实:

  1. 纯Python模块总是使用设置为字符串"__main__"的变量__name__创建的。

  2. 导入模块的副作用是将__name__变量更改为没有.py扩展名的基本文件名。

如何使用这些信息

人们编写__name__ == '__main__'来测试模块是否已导入。

通常会有一些在导入发生时不应该运行的代码:测试代码、一次性使用代码、命令行前端或Web服务器前端。

这个想法是,运行模块的人直接希望这些操作发生,但导入模块的人只希望直接访问函数、类和变量。

从其他答案中可以看出,人们似乎能够无休止地谈论这个话题,但它确实是一件简单的事情,很容易掌握。Python教程涵盖这大约两分钟值得阅读。不要让其他答案过度解释淹没你:-)

当您import某些具有此条件的代码时,它将返回False(在导入的代码中),但将为将要运行的代码返回True

if __name__ == "__main__":防止在导入文件时运行不需要的代码。

例如,这是没有#1#0

# "test1.py"
def hello()print("Hello")
hello()

#0只是导入#1

# "test2.py"
import test1 # Here

然后,当运行#0时,会打印一个#1,因为#3中的不需要的代码#2也会运行:

python test2.pyHello

当然,您可以在#1中调用#0

# "test2.py"
import test1
test1.hello() # Here

然后,当运行#0时,打印两个#1

python test2.pyHelloHello

现在,将#0添加到#1并将#2放在下面:

# "test1.py"
def hello()print("Hello")
if __name__ == "__main__":hello()

这是#0

# "test2.py"
import test1
test1.hello()

然后,当运行#0时,打印只有一个#1,因为#2阻止在#0导入Hello1时运行不需要的代码#3

python test2.pyHello

此外,无论#0是否有#1

# "test1.py"
def hello()print("Hello")
if __name__ == "__main__":hello()
# "test1.py"
def hello()print("Hello")
hello()

一个#0在运行#1时正确打印:

python test1.pyHello