python:if __name__ == “__main__”是什么意思?

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Threading example
import time, thread

def myfunction(string, sleeptime, lock, *args):
    while True:
        lock.acquire()
        time.sleep(sleeptime)
        lock.release()
        time.sleep(sleeptime)

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))

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

它设置了一些特殊的变量,比如__name__,然后

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

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

代码示例

让我们使用稍微不同的代码示例来研究导入和脚本是如何工作的。假设以下内容在一个名为foo.py的文件中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 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")

特殊变量

当Python interpeter读取源文件时,它首先定义几个特殊的变量。在本例中,我们关心的是__name__变量。

当您的模块是主程序时

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

1
python foo.py

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

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

当模块被其他模块导入时

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

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

在本例中,解释器将查看模块的文件名foo.py,去掉.py,并将该字符串分配给模块的__name__变量,即

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

执行模块代码

在设置了特殊变量之后,解释器执行模块中的所有代码,每次执行一条语句。您可能想在代码示例旁边打开另一个窗口,这样您就可以按照这个解释来操作了。

总是

它输出字符串"before import"(不带引号)。

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

1
2
3
# Find and load a module given its string name,"math",
# then assign it to a local variable called math.
math = __import__("math")

它打印字符串"before functionA"

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

它打印字符串"before functionB"

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

它打印字符串"before __name__ guard"

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

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

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

(相反)如果您的模块不是主程序,而是由另一个程序导入的,那么__name__将是"foo",而不是"__main__",它将跳过if语句的主体。

总是

它将在两种情况下打印字符串"after __name__ guard"

总结

总之,以下是两种情况下的打印结果:

1
2
3
4
5
6
7
8
# What gets printed if foo is the main program
before import
before functionA
before functionB
before __name__ guard
Function A
Function B 10.0
after __name__ guard
1
2
3
4
5
6
# What gets printed if foo is imported as a regular module
before import
before functionA
before functionB
before __name__ guard
after __name__ guard

它为什么这样工作?

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

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

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

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

除了这些例子之外,用Python运行脚本只需设置一些神奇的变量并导入脚本,这是非常优雅的。"运行"脚本是导入脚本模块的副作用。

精神食粮

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

假设下面的代码在foo2.py中。如果在命令行上输入python foo2.py会发生什么?为什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Suppose this is foo2.py.

def functionA():
    print("a1")
    from foo2 import functionB
    print("a2")
    functionB()
    print("a3")

def functionB():
    print("b")

print("t1")
if __name__ =="__main__":
    print("m1")
    functionA()
    print("m2")
print("t2")

现在,计算一下如果删除__name__ check in foo3.py会发生什么:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Suppose this is foo3.py.

def functionA():
    print("a1")
    from foo3 import functionB
    print("a2")
    functionB()
    print("a3")

def functionB():
    print("b")

print("t1")
print("m1")
functionA()
print("m2")
print("t2")

当用作脚本时,它会做什么?当作为模块导入时?

1
2
3
4
5
6
7
8
9
10
# Suppose this is in foo4.py
__name__ ="__main__"

def bar():
    print("bar")

print("before __name__ guard")
if __name__ =="__main__":
    bar()
print("before __name__ guard")


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

1
python myscript.py

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

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

1
2
if __name__ =="__main__":
    ...

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

1
2
3
4
5
6
7
8
9
10
# file one.py
def 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")
1
2
3
4
5
6
7
8
9
10
# file two.py
import 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")

现在,如果您调用解释器as

1
python one.py

输出将是

1
2
top-level in one.py
one.py is being run directly

如果你运行two.py代替:

1
python two.py

你得到

1
2
3
4
5
top-level in one.py
one.py is being imported into another module
top-level in two.py
func() in one.py
two.py is being run directly

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


__name__变量(imho)最简单的解释如下:

创建以下文件。

1
2
# a.py
import b

1
2
3
4
5
# b.py
print"Hello World from %s!" % __name__

if __name__ == '__main__':
    print"Hello World again from %s!" % __name__

运行它们会得到如下输出:

1
2
$ python a.py
Hello World from b!

可以看到,当导入模块时,Python将该模块中的globals()['__name__']设置为模块的名称。此外,在导入模块中的所有代码后,将运行模块中的所有代码。由于if语句的计算结果是False,因此不执行此部分。

1
2
3
$ python b.py
Hello World from __main__!
Hello World again from __main__!

可以看到,当执行一个文件时,Python将该文件中的globals()['__name__']设置为"__main__"。这一次,if语句的计算结果是True,并且正在运行。


What does the if __name__ =="__main__": do?

概述基本知识:

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

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

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

我们为什么需要这个?

开发和测试您的代码

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

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

您可以通过在底部添加这个函数调用来测试模块:

1
do_important()

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

1
~$ python important.py

问题

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

1
import important

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

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

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

一个更好的方法

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

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

但是在主模块(或交互式Python会话,即解释器的Read、Eval、Print Loop或REPL)中,您可以运行从它的"__main__"开始的所有内容。

所以如果你在执行前检查:

1
2
if __name__ =="__main__":
    do_important()

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

一个更好的方法

不过,有一种python式的方法可以改进这一点。

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

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

1
2
3
4
5
6
7
8
9
10
11
12
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__'模块运行时调用模块(及其函数和类),即

1
2
import important
important.main()

在Python文档中对__main__模块的解释中也可以找到这个习语。文本:

This module represents the (otherwise anonymous) scope in which the
interpreter’s main program executes — commands read either from
standard input, from a script file, or from an interactive prompt. It
is this environment in which the idiomatic"conditional script" stanza
causes a script to run:

1
2
if __name__ == '__main__':
    main()


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


What does if __name__ =="__main__": do?

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

但是,作为唯一的特殊情况,在您运行的任何Python进程中,如mycode.py:

1
python mycode.py

否则匿名的全局名称空间将'__main__'的值赋给它的__name__

因此,包括最后一行

1
2
if __name__ == '__main__':
    main()

在mycode.py脚本的末尾,当它是由Python进程运行的主要入口点模块时,

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

使用这种结构的另一个好处是:您还可以将代码作为模块导入另一个脚本中,然后在程序决定:

1
2
3
import mycode
# ... any amount of other code
mycode.main()

这里有很多关于代码机制的不同观点,比如"如何",但是对我来说,在我理解"为什么"之前,这些观点都没有任何意义。这对新程序员尤其有用。

把文件"ab.py":

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

第二个文件"xy.py":

1
2
3
4
5
6
7
8
import ab
def 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()

What is this code actually doing?

当您执行xy.py时,您将执行import ab。import语句在导入时立即运行模块,因此ab的操作在xy的其余操作之前执行。一旦使用ab结束,它将继续使用xy

解释器跟踪使用__name__运行的脚本。当您运行一个脚本时(无论您将它命名为什么),解释器都将它称为"__main__",使它成为在运行外部脚本之后返回的主脚本或"home"脚本。

从这个"__main__"脚本调用的任何其他脚本的文件名都被指定为它的__name__(例如,__name__ =="ab.py")。因此,if __name__ =="__main__":行是解释器的测试,以确定它是在解释/解析最初执行的"home"脚本,还是在临时查看另一个(外部)脚本。这给了程序员灵活性,让脚本在直接执行和外部调用时表现不同。

让我们逐步了解上面的代码,首先关注未缩进的行以及它们在脚本中出现的顺序。请记住,函数(或def)在被调用之前不会自己执行任何操作。翻译自言自语时可能会说什么:

打开xy.py作为"home"文件;在__name__变量中调用它"__main__"。使用__name__ =="ab.py"导入并打开文件。哦,一个函数。我会记住。好的,函数a();我刚学的。打印"ab文件中的函数"。文件结束;回到"__main__" !哦,一个函数。我会记住。另一个。函数x();好的,打印"外围任务:可能在其他项目中有用"。这是什么?if语句。条件已经满足(变量__name__被设置为"__main__"),因此我将输入main()函数并打印"main function: this is where the action is"。

下面两行表示:"如果这是"__main__"或'home'脚本,则执行名为main()的函数"。这就是为什么您将在顶部看到一个def main():块,它包含脚本功能的主要流程。

Why implement this?

还记得我之前说过的导入语句吗?当您导入一个模块时,它不仅仅"识别"它并等待进一步的指令——它实际上运行脚本中包含的所有可执行操作。因此,将脚本的主体放入main()函数中可以有效地对其进行隔离,使其处于隔离状态,以便在被其他脚本导入时不会立即运行。

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

But the code works without it

是的,这是正确的。这些单独的函数可以从没有包含在main()函数中的内联脚本中调用。如果您已经习惯了(就像我一样,在我早期的编程学习阶段)构建符合您需要的内联脚本,并且如果您再次需要该操作,您将尝试重新找出它……你不习惯这种代码的内部结构,因为它构建起来更复杂,读起来也不那么直观。

但是这个脚本可能不能在外部调用它的函数,因为如果调用了函数,它将立即开始计算和分配变量。而且,如果您试图重用一个函数,那么您的新脚本可能与旧脚本紧密相关,因此会出现冲突的变量。

通过分离独立的函数,您可以通过将它们调用到另一个脚本中来重用以前的工作。例如,"的例子。py"可能导入"xy。和调用x(),使用"xy.py"中的"x"函数。(可能是将给定文本字符串的第三个单词大写;从数字列表中创建一个NumPy数组并对其平方;或使三维曲面失稳。可能性是无限的。

(顺便提一句,这个问题的答案来自@kindall,它最终帮助我理解了为什么,而不是如何。不幸的是,它被标记为这个的复制品,我认为这是一个错误。)


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

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

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


让我们从一个更抽象的角度来看这个问题的答案:

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

1
2
3
4
5
...
<Block A>
if __name__ == '__main__':
    <Block B>
...

当我们运行"x.py"时,将运行块A和块B。

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


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

如果我们有两个脚本;

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

1
2
3
#script2.py
import script1
print"Script 2's name: {}".format(__name__)

执行script1的输出为

1
Script 1's name: __main__

执行script2的输出为:

1
2
Script1's name is script1
Script 2'
s name: __main__

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

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

Complicated importing in C

箭头是导入链接。对于三个试图包含前面模块代码的模块,每个模块有6个文件(包括9个实现文件)和5个链接。这使得将其他代码包含到C项目中变得非常困难,除非它被特别编译为一个库。现在想象一下Python:

Elegant importing in Python

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


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

1
2
3
4
5
6
7
8
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.

考虑:

1
2
if __name__ =="__main__":
    main()

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

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


在解释关于if __name__ == '__main__'的任何内容之前,理解__name__是什么以及它做什么是很重要的。

What is __name__?

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

它是一个由type(__name__)(生成)表示的字符串(如上所述是全局的),是Python 3和Python 2版本的内置标准。

Where:

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

翻译:

1
2
3
>>> print(__name__)
__main__
>>>

脚本:

test_file.py:

1
print(__name__)

导致__main__

模块或包:

somefile.py:

1
2
def somefunction():
    print(__name__)

test_file.py:

1
2
import somefile
somefile.somefunction()

导致somefile

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

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

Practice:

作为一个变量意味着它的值可以被覆盖("can"并不意味着"should"),覆盖__name__的值将导致可读性的缺乏。所以不要这样做,不管什么原因。如果需要一个变量,定义一个新变量。

通常假定__name__的值为__main__或文件名。再次更改这个默认值将会导致更多的混淆,而不是认为它很好,从而导致进一步的问题。

例子:

1
2
3
4
5
6
7
>>> __name__ = 'Horrify' # Change default from __main__
>>> if __name__ == 'Horrify': print(__name__)
...
>>> else: print('Not Horrify')
...
Horrify
>>>

一般来说,在脚本中包含if __name__ == '__main__'被认为是很好的实践。

Now to answer if __name__ == '__main__':

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

if是一个流控制语句,如果给定的值为真,则包含代码块。我们已经看到__name__可以选择任何一种__main__或从其中导入的文件名。

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

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

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

Modules:

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

Variants:

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

只有当文件是模块或包时才执行:

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

运行一个条件,如果文件是主要的,另一个条件,如果不是:

1
2
3
4
if __name__ == '__main__':
    # Execute something
else:
    # Do some useful things

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

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


我认为最好是用简单的语言深入地回答这个问题:

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

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

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


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

它可以用几种方式来写。另一个原因是:

1
2
3
4
5
def some_function_for_instance_main():
    dosomething()


__name__ == '__main__' and some_function_for_instance_main()

我并不是说您应该在生产代码中使用它,但是它说明了if __name__ == '__main__'并没有什么"神奇"之处。这是在Python文件中调用主函数的一个很好的约定。


系统(Python解释器)为源文件(模块)提供了许多变量。您可以在任何时候获得它们的值,因此,让我们关注于……name__变量/属性:

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

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

如果Python将这个源代码文件加载为主程序(即您运行的文件),那么它将为这个文件设置一个特殊的……name__变量,使其值为"……main__"。

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

在你的例子中

1
2
3
4
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))

表示代码块:

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

只会在直接运行模块时执行;如果另一个模块调用/导入代码块,代码块将不会执行,因为在该特定实例中,_name__的值将不等于"main"。

希望这能有所帮助。


if __name__ =="__main__":基本上是顶级脚本环境,它指定解释器('I have the highest priority to be execution first')。

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

1
2
3
if __name__ =="__main__":
    # Execute only if run as a script
    main()

的原因

1
2
if __name__ =="__main__":
    main()

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

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


我在这一页上读了很多答案。我想说的是,如果你知道这件事,你肯定会理解这些答案,否则,你仍然会感到困惑。

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

import a action实际上运行所有可以在"a"中运行的操作

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

要解决第2点中的问题,python允许您进行条件检查

__name__是所有.py模块中的隐式变量;导入a.py时,将a.py模块的__name__值设置为其文件名"a";当a.py直接使用"python a"运行时。,表示a.py为入口点,将a.py模块的__name__值设置为字符串__main__

根据python为每个模块设置变量__name__的机制,您知道如何实现第3点吗?答案很简单,对吧?输入if条件:if __name__ =="__main__": ...;根据您的功能需求,您甚至可以输入if __name__ =="a"

python的特殊之处在于第4点!剩下的只是基本的逻辑。


You can make the file usable as a script as well as an importable module.

py(一个名为fibo的模块)

1
2
3
4
5
6
7
8
9
10
11
12
# Other modules can IMPORT this MODULE to use the function fib
def fib(n):    # write Fibonacci series up to n
    a, b = 0, 1
    while b < n:
        print(b, end=' ')
        a, b = b, a+b
    print()

# This allows the file to be used as a SCRIPT
if __name__ =="__main__":
    import sys
    fib(int(sys.argv[1]))

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


考虑:

1
print __name__

上面的输出是__main__

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

以上语句为真,打印"direct method"。假设他们在另一个类中导入这个类,它不会打印"direct method",因为在导入时,它会设置__name__ equal to"first model name"


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

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

它通常是为测试而编写的。


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

从其他文件调用该类。你只需要在调用程序中导入它。

为了测试的目的,单独运行类。

对于后一种情况,类应该包含一个公共静态void main()方法。在Python中,这个目的由全局定义的标签'__main__'来实现。


创建一个文件a.py:

1
print(__name__) # It will print out __main__

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

创建另一个文件b。,在同一目录下:

1
import a  # Prints a

运行它。它将输出a,即。,即导入的文件的名称。

因此,要显示同一个文件的两种不同行为,这是一个常用的技巧:

1
2
3
4
# 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__ == '__main__':

它检查模块是否被导入。

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

让我们看看它是如何使用一个简单的代码打印模块的名称:

1
2
3
4
5
6
7
# test.py
def test():
   print('test module name=%s' %(__name__))

if __name__ == '__main__':
   print('call test()')
   test()

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

1
2
call test()
test module name=__main__

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

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

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

这就是这行代码所检查的。如果它是主文件(即, b.py)运行该代码,在本例中它不是(a.py是正在运行的主文件),然后只执行该代码。


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