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

答案:


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

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

在你的脚本的情况下,让我们假设它正在执行作为主要功能,例如你说了类似的东西

python threading_example.py

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

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

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

 

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

python myscript.py

所有处于缩进级别0的代码都会被执行。定义的函数和类已经定义好了,但是没有任何代码可以运行。与其他语言不同,没有main()自动运行的main()功能- 该功能隐含在顶层的所有代码。

在这种情况下,顶级代码是一个if块。 __name__是一个内置变量,用于评估当前模块的名称。但是,如果模块正在直接运行(myscript.py如上所述),则将__name__其设置为字符串"__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__"

 

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

什么是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函数将被调用,因此您可能会在底部注释掉该函数的调用。然后你必须记住你是否注释掉了你的测试函数调用。而这种额外的复杂性意味着你可能会忘记,使你的开发过程更麻烦。

更好的方法

__name__变量指向Python解释器恰好在此刻的任何地方的名称空间。在导入的模块中,它是该模块的名称。但在主模块(或交互式Python会话,即解释器的读取,评估,打印循环或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()

添加评论

友情链接:蝴蝶教程