题 如果__name__ ==“__ main__”:怎么办?


什么是 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))

4149
2018-01-07 04:11


起源




答案:


当Python解释器读取源文件时,它会执行其中的所有代码。

在执行代码之前,它将定义一些特殊变量。例如,如果Python解释器将该模块(源文件)作为主程序运行,则它将设置特殊 __name__ 变量有一个值 "__main__"。如果从另一个模块导入此文件, __name__ 将被设置为模块的名称。

在你的脚本的情况下,让我们假设它作为主要功能执行,例如你说的话

python threading_example.py

在命令行上。设置特殊变量后,它将执行 import 声明并加载这些模块。然后它将评估 def 阻止,创建一个函数对象并创建一个名为的变量 myfunction 指向函数对象。然后它将读取 if 声明并看到了 __name__ 确实相等 "__main__",所以它将执行那里显示的块。

这样做的一个原因是有时候你会写一个模块(a .py 文件)它可以直接执行。或者,它也可以导入并在另一个模块中使用。通过执行主检查,您可以仅在希望将模块作为程序运行时执行该代码,而在有人只想导入模块并自行调用函数时不执行该代码。

看到 这一页 一些额外的细节。


4421
2018-01-07 04:26



注意:如果将代码放在函数定义之前,它将在main之前执行。 print("This code executes before main.") def functionA(): print("Function A") def functionB(): print("Function B") if __name__ == '__main__': functionA() functionB()  此代码导致: This code executes before main. Function A Function B - Stainsor


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

python myscript.py

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

在这种情况下,顶级代码是 if 块。 __name__ 是一个内置变量,它计算当前模块的名称。但是,如果正在直接运行模块(如 myscript.py 以上),然后 __name__ 而是设置为字符串 "__main__"。因此,您可以通过测试来测试脚本是直接运行还是由其他内容导入

if __name__ == "__main__":
    ...

如果您的脚本被导入到另一个模块中,它的各种函数和类定义将被导入并且它的顶级代码将被执行,但是那个代码在then-body中 if 由于条件不满足,上述条款不会运行。作为基本示例,请考虑以下两个脚本:

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


1415
2018-01-07 04:28



精彩的解释。 - Poles


最简单的解释 __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__'] 在这个模块中的模块名称。

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

如您所见,当执行文件时,Python会设置 globals()['__name__'] 在这个文件中 "__main__"


562
2018-01-07 11:35





什么是 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 important
important.main()

这个成语也可以在Python文档的解释中找到 __main__ 模块。 该文字指出:

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

if __name__ == '__main__':
    main()

413
2017-11-23 04:38





if __name__ == "__main__"是使用类似命令从命令行运行脚本时运行的部分 python myscript.py


92
2018-01-07 04:14





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

__name__ 是一个全局变量(在Python中,全局实际意味着在 模块级别)存在于所有名称空间中。它通常是模块的名称(作为 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()

57
2017-10-14 20:22





这里有很多不同的关于代码的机制,“如何”,但对我来说,除非我理解“为什么”,否则它们都没有意义。这应该对新程序员特别有用。

取文件“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__": 是解释器的测试,用于确定它是否正在解释/解析最初执行的“主页”脚本,或者它是否暂时窥视另一个(外部)脚本。这为程序员提供了灵活性,使脚本的行为不同,如果它直接执行而不是外部调用。

让我们逐步完成上面的代码来了解发生了什么,首先关注的是未缩进的行以及它们在脚本中出现的顺序。记住这个功能 - 或者 def  - 块在被调用之前不会自己做任何事情。如果嘟to自己,翻译可能会说些什么:

  • 打开xy.py作为“主页”文件;叫它 "__main__" 在里面 __name__ 变量。
  • 导入并打开文件 __name__ == "ab.py"
  • 哦,一个功能。我会记得的。
  • 好的,功能 a();我刚学会了这个。印刷'ab文件中的一个函数”。
  • 文件结束;回到 "__main__"
  • 哦,一个功能。我会记得的。
  • 另一个。
  • 功能 x();好的,打印'外围任务:在其他项目中可能有用”。
  • 这是什么?一个 if 声明。嗯,条件已经满足(变量 __name__已经设定为 "__main__"),所以我会进入 main() 功能和打印'主要功能:这是动作的所在”。

底部的两行意味着:“如果这是 "__main__" 或'home'脚本,执行调用的函数 main()“那就是为什么你会看到一个 def main(): 阻止顶部,其中包含脚本功能的主要流程。

为什么实现这个?

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

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

但代码在没有它的情况下工作

恩,那就对了。这些单独的功能 能够 从一个未包含在内部的内联脚本中调用 main() 功能。如果你已经习惯了(就像我在编程的早期学习阶段一样)构建完全符合你需要的内联脚本,如果你再次需要这个操作,你会尝试再次弄清楚它。好吧,你不习惯你的代码的这种内部结构,因为它构建起来更复杂,而且阅读不那么直观。

但这是一个可能无法在外部调用其函数的脚本,因为如果这样做,它会立即开始计算和分配变量。如果你正在尝试重新使用某个函数,那么你的新脚本可能与旧版本密切相关,而且会有相互矛盾的变量。

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

(作为旁白, 这个问题 包含@kindall的答案,最终帮助我理解 - 为什么,而不是如何。不幸的是,它被标记为重复 这个,我认为这是一个错误。)


47
2017-09-29 04:33





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

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

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


39
2018-04-03 14:09





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

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

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

当我们运行“x.py”时,块A和B运行。

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


32
2018-01-20 17:48





当您以交互方式运行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.

30
2017-12-11 11:23





简单地说, __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__ 告诉我们哪个代码是'main'模块。 这很好,因为你可以只编写代码而不必担心C / C ++中的结构问题,如果文件没有实现'main'函数那么它就不能编译为可执行文件,如果是,它不能用作库。

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

Complicated importing in C

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

Elegant importing in Python

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


29
2017-10-15 09:07



C / C ++插图错误:相同单位名称的3倍(文件1)。 - Wolf