__name__ ==“ __main__”怎么办?


6055

给定以下代码,该if __name__ == "__main__":怎么办?

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

if __name__ == "__main__":到Python 3为止,块条件是否已经过时/过时了?我发现一些信息说明了这一点。
carloswm85

1
@ carloswm85不是这样。
Giorgos Myrianthous

Answers:


6634

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

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

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

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

代码样例

让我们使用稍微不同的代码示例来探索导入和脚本的工作方式。假设以下文件位于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")

特殊变量

当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 functionA"

  2. 它执行该def块,创建一个功能对象,然后将该功能对象分配给名为的变量functionA

  3. 它输出字符串"before functionB"

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

  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 program
before import
before functionA
before functionB
before __name__ guard
Function A
Function B 10.0
after __name__ guard
# 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在命令行上说会怎样?为什么?

# 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__签入会发生什么foo3.py
# 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")
  • 当用作脚本时,它将做什么?当作为模块导入时?
# Suppose this is in foo4.py
__name__ = "__main__"

def bar():
    print("bar")

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

14
出于好奇:如果我subprocess.run('foo_bar.py')在python脚本中运行,会发生什么情况?我想这foo_bar将从__name__ = '__main__'foo_bar.py手动输入cmd 时开始。是这样吗 考虑到@MrFooz的答案,这样做应该没有问题,并且一次可以拥有多个“主要”模块。即使更改__name__值或具有多个独立创建的实例(或通过彼此创建的实例subprocess)彼此交互也应该与Python照常进行。我想念什么吗?
hajef

12
@hajef您对事情的工作方式是正确的subprocess.run。也就是说,在脚本之间共享代码的通常更好的方法是创建模块,并使脚本调用共享的模块,而不是像脚本那样相互调用。很难调试subprocess.run电话,因为大多数调试不跨进程边界跳时,可加不平凡的系统开销创建和销毁多余的进程等
福兹先生

4
我对食品的思考部分的foo2.py示例有疑问。从foo2.py导入functionB做什么?在我看来,它只是从functionB导入foo2.py
user471651 '19

1
@MrFooz我从没打算做过类似xD的事情。将他们的想法包罗万象。@ user471651为什么应从from foo2 import functionBfunctionB导入foo2?那是语义上的扭曲。from module import method从模块导入方法。
hajef

2
可能会导入代码的模块之一是multiprocessing,尤其是在Windows上使此测试成为必需。
Yann Vernier

1799

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

python myscript.py

缩进级别为0的所有代码都将执行。可以很好地定义已定义的函数和类,但是不会运行任何代码。与其他语言不同,它没有main()自动运行的功能-main()函数隐式是顶层的所有代码。

在这种情况下,顶级代码是一个if块。 __name__是一个内置变量,其结果为当前模块的名称。但是,如果模块直接运行(如上myscript.py所示),则将__name__其设置为string "__main__"。因此,您可以通过测试来测试您的脚本是直接运行还是通过其他方式导入

if __name__ == "__main__":
    ...

如果将脚本导入另一个模块,则将导入其各种功能和类定义,并执行其顶层代码,但是上述if子句的then-body中的代码将不会运行,因为条件是没见过。作为一个基本示例,请考虑以下两个脚本:

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

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

python one.py

输出将是

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

如果two.py改为运行:

python two.py

你得到

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__"


很棒的答案,在我看来,这是最清晰的答案。+1!
TheTechRobo36414519

+1的思考方式:仅在第一行开始运行缩进线,直到您在第一行运行功能为止
Eli TheHuman

719

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

创建以下文件。

# a.py
import b

# b.py
print "Hello World from %s!" % __name__

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

运行它们将为您提供以下输出:

$ python a.py
Hello World from b!

如您所见,导入模块时,Python globals()['__name__']在此模块中设置模块的名称。同样,在导入时,模块中的所有代码都在运行。由于if语句评估到False这一部分没有执行。

$ python b.py
Hello World from __main__!
Hello World again from __main__!

如您所见,执行文件时,Python globals()['__name__']在该文件中将设置为"__main__"。这次,该if语句求值True并正在运行。


513

怎么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()

有了以上内容,您的代码将仅在以主模块运行(或从另一个脚本有意调用)时执行。

更好的方法

不过,有一种Python方式可以对此进行改进。

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

如果我们放上我们想在开发和测试这样的函数时使用的代码,然后在执行以下操作时'__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 important
important.main()

这个习语也可以在Python文档中的__main__模块说明中找到。该文本指出:

此模块表示解释程序的主程序在其中执行的(否则为匿名)范围-从标准输入,脚本文件或交互式提示中读取的命令。在这种环境中,惯用的“条件脚本”节使脚本运行:

if __name__ == '__main__':
    main()

125

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


2
为什么helloworld.py只包含一个文件的文件即使没有print("hello world")也可以用命令运行?python helloworld.pyif __name__ == "__main__"
hi15

83

怎么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 code
mycode.main()

72

在这里,有关代码的“如何”的机制有很多不同之处,但是对我而言,直到我理解了“为什么”之后,才有意义。这对新程序员特别有用。

取得文件“ ab.py”:

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

还有第二个文件“ xy.py”:

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

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

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

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

从该"__main__"脚本调用的任何其他脚本都被分配了其文件名作为其文件名__name__(例如__name__ == "ab.py")。因此,线if __name__ == "__main__":是解释程序的测试,以确定它是否正在解释/解析最初执行的“ home”脚本,或者它是否正在临时窥视另一个(外部)脚本。这使程序员可以灵活地让脚本在直接执行与在外部执行之间有所不同。

让我们逐步看一下上面的代码,以了解发生了什么,首先关注未缩进的行及其在脚本中出现的顺序。请记住,函数-或def-块在被调用之前不会自行执行任何操作。如果自言自语,口译员可能会说:

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

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

为什么要实施呢?

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

同样,会有例外,但是通常的做法是main()通常不会在外部调用它。因此,您可能想知道又一件事:如果我们不调用main(),为什么还要调用脚本呢?这是因为许多人使用独立的函数来构造脚本,这些独立的函数旨在独立于文件中的其余代码运行。然后在脚本正文中的其他位置调用它们。这使我想到了这一点:

但是代码没有它就可以工作

恩,那就对了。可以从函数未包含的内联脚本中调用这些单独的main()函数。如果您习惯了(就像我在编程的早期学习阶段那样)构建可以完全满足您需要的内联脚本,并且如果您再次需要该操作,那么您将尝试再次找出它。嗯,您不习惯这种代码的内部结构,因为它的构建更加复杂并且阅读起来也不那么直观。

但这是一个脚本,可能无法从外部调用其功能,因为如果执行该脚本,它将立即开始计算和分配变量。而且,如果您想重用某个功能,则新脚本与旧脚本的关联性可能会很高,以至于变量会冲突。

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

(顺便说一句,这个问题包含@kindall的答案,它最终帮助我理解了-原因,而不是方法。不幸的是,它被标记为与副本的副本,我认为这是错误的。)


52

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

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

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


43

简而言之,__name__是为每个脚本定义的变量,用于定义脚本是作为主模块运行还是作为导入模块运行。

因此,如果我们有两个脚本;

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

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

执行script1的输出是

Script 1's name: __main__

执行script2的输出是:

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

如你看到的, __name__告诉我们哪个代码是“主”模块。这很棒,因为您可以编写代码,而不必担心C / C ++中的结构性问题,在这种情况下,如果文件未实现“ main”功能,则无法将其编译为可执行文件,如果可以,然后它不能用作库。

假设您编写的Python脚本功能出色,并实现了许多对其他用途有用的功能。如果要使用它们,我可以导入您的脚本并使用它们而无需执行您的程序(假设您的代码仅在if __name__ == "__main__":上下文中执行 )。而在C / C ++中,您将必须将这些部分分成一个单独的模块,然后再包含文件。如下图所示;

用C导入复杂

箭头是导入链接。对于三个试图包含先前模块代码的模块,有六个文件(九个,计算实现文件)和五个链接。除非将其专门编译为库,否则很难将其他代码包含到C项目中。现在将其描述为适用于Python:

用Python优雅地导入

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


2
C / C ++插图是错误的:3倍相同的单元名称(file1)。

40

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

假设我们在以下代码中x.py

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

块A和B,当我们正在运行的运行x.py

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


1
我无法编辑帖子(如果需要更改,最少6个字符)。第14行具有“ xy”而不是“ x.py”。
AlwaysLearning

35

交互式运行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.

34

考虑:

if __name__ == "__main__":
    main()

它检查__name__Python脚本的属性是否为"__main__"。换句话说,如果程序本身已执行,则属性将为__main__,因此程序将被执行(在这种情况下,main()函数)。

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


似乎为发光的答案+1写了太长时间了
snr

27

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

什么__name__

__name__DunderAlias-可以认为是全局变量(可从模块访问),并且与相似global

它是type(__name__)(yielding <class 'str'>)指示的字符串(如上所述),并且是Python 3Python 2版本的内置标准。

哪里:

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

口译员:

>>> print(__name__)
__main__
>>>

脚本:

test_file.py

print(__name__)

导致 __main__

模块或包装:

somefile.py:

def somefunction():
    print(__name__)

test_file.py:

import somefile
somefile.somefunction()

导致 somefile

请注意,在包或模块中使用时,使用__name__文件名。没有给出实际模块或包路径的路径,但是具有自己的DunderAlias__file__,因此可以这一点。

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

实践:

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

始终假定__name__为be 的值__main__或文件名。再次更改此默认值将引起更多混乱,这会带来好处,并进一步导致问题。

例:

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

通常,将if __name__ == '__main__'in 包含在脚本中被认为是一种好习惯。

现在回答if __name__ == '__main__'

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

一个if是包含的代码块,如果给定的值是true,将执行流控制语句。我们已经看到这__name__可以采取 __main__导入的文件名导入的文件名。

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

如果确实__name__采用了值,__main__那么该代码块中的所有内容都将执行。

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

模块:

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

变体:

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

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

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

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

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

您也可以使用它在软件包和模块上提供可运行的帮助功能/实用程序,而无需精心使用库。

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


25

我认为最好是深入浅出的答案:

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

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

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


23

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

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

def some_function_for_instance_main():
    dosomething()


__name__ == '__main__' and some_function_for_instance_main()

我并不是说您应该在生产代码中使用它,但是它可以说明没有什么“魔术” if __name__ == '__main__'。在Python文件中调用主函数是一个很好的约定。


7
我认为这是一种不好的形式,因为您1)依赖副作用,2)滥用andand用于检查两个布尔语句是否都为真。既然你不在的结果感兴趣and,一个if说法更清楚地表达你的意图。
jpmc26 2013年

8
抛开将布尔运算符的短路行为用作流控制机制是否是坏习惯的问题,更大的问题是,这根本无法回答问题
Mark Amery 2015年

@MarkAmery哈哈,嘘,现在可以了。😊
法尔肯教授合约突破

19

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

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

但是,在解释器执行源代码文件之前,它会为该文件定义一些特殊的变量。__名称__是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__的值在该特定实例中将不等于“ main ”。

希望这会有所帮助。


17

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

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

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

17

在本页的所有答案中,我都读了很多东西。我想说的是,如果您知道这件事,那么您肯定会理解这些答案,否则,您仍然会感到困惑。

简而言之,您需要了解以下几点:

  1. import a 操作实际上会运行所有可以在“ a”中运行的内容

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

  3. 为了解决第2点的问题,python允许您进行条件检查

  4. __name__是所有.py模块中的隐式变量;当a.py被导入,的值__name__a.py模块设置为它的文件名“ a“; 当a.py直接使用运行“ python a.py”,该装置a.py在所述入口点,则该值__name__a.py模块被设置为一个字符串__main__

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

python特殊之处很重要的一点是第4点!其余只是基本逻辑。


1
是的,要理解这一点至关重要。由此可见,对这种机制的需求变得清晰起来。
尤里卡

16

考虑:

print __name__

上面的输出是__main__

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

上面的陈述是正确的,并显示“ direct method”。假设他们在另一个类中导入了该类,则不会打印“直接方法”,因为在导入时它将设置__name__ equal to "first model name"


14

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

fibo.py(名为的模块fibo

# 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


14

的原因

if __name__ == "__main__":
    main()

主要是为了避免由于直接导入代码而导致的导入锁定问题。你想运行,如果是直接调用的文件(这是main()__name__ == "__main__"情况),,但是如果导入了代码,则导入程序必须从真正的主模块输入代码,以避免导入锁定问题。

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


3
很高兴了解导入锁定。您能否解释一下更进一步的登录方法

1
@狼:当然。我添加了关于多入口点方法的几句话。
personal_cloud

11

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

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

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

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


11

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'

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


第二种可能性: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'

10

python中的每个模块都有一个名为的属性__name____name__ attribute 的值__main__ 是直接运行模块时(例如)python my_module.py。否则(如您说的那样import my_module)的值__name__ 是模块的名称。

简短说明一下小例子。

#Script 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_world
I am inside hello_world

现在假设我们从其他脚本中调用上述脚本

#script external_calling.py

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

print(test.__name__)

当您执行此

python external_calling.py

输出量

42
I am inside hello_world
test

所以,以上是自我解释,当你调用其他脚本的测试,如果循环__name__test.py不会执行。


6

如果此.py文件是由其他.py文件导入的,则“ if语句”下的代码将不会执行。

如果此.py是python this_py.py在shell下运行,或在Windows中双击。“ if语句”下的代码将被执行。

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


6

如果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,则if __name__ == "__main__"文件A中的文件将变为false,因此将其打印出来 您看不到我

b


5

所有答案都对功能进行了解释。但是,我将提供其用法的一个示例,这可能有助于进一步澄清该概念。

假设您有两个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是主文件),则仅执行代码。


4

创建一个文件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

4

如果name ==' main ':

我们__name__ == '__main__':经常查看。

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

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

让我们看一下使用打印模块名称的简单代码的作用:

# test.py
def test():
   print('test module name=%s' %(__name__))

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

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

call test()
test module name=__main__

4

简而言之,就像C编程语言中的main函数一样,它是运行文件的入口。


8
该答案假设OP(或具有类似问题的任何用户)都熟悉C 并且知道入口点是什么。
Arredond

1
该答案还假定在该if __name__ == "__main__"块之前没有发生任何代码(除了没有副作用的定义之外)。从技术上讲,执行脚本的顶部是程序的入口点。
查理·哈丁
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.