python main函数 - 如果__name__ ==“__ main__”:怎么办?


13 Answers

通过将脚本作为命令传递给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__"

Question

python __name__用法

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__":是什么意思?

概述基础知识:

  • 作为程序入口点的模块中的全局变量__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()



if __name__ == "__main__":怎么办?

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

然而,作为唯一的特殊情况,无论你在哪个Python进程中运行,如在mycode.py中:

python mycode.py

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

因此,包括最后一行

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

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

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

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



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

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

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




简而言之, __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__": context中执行)。 而在C / C ++中,您必须将这些部分分成一个单独的模块,然后包含该文件。 想象下面的情况;

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

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




考虑:

if __name__ == "__main__":
    main()

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

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




系统(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__的值在该特定实例中不等于“ main ”。

希望这会有所帮助。




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

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

def some_function_for_instance_main():
    dosomething()


__name__ == '__main__' and some_function_for_instance_main()

我并不是说你应该在生产代码中使用它,但它可以说明if __name__ == '__main__'没有任何“神奇”。 在Python文件中调用main函数是一个很好的约定。




的原因

if __name__ == "__main__":
    main()

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

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




考虑:

print __name__

上面的输出是__main__

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

以上陈述是正确的,并打印“直接方法” 。 假设他们在其他类中导入了这个类,它不会打印“直接方法”,因为在导入时,它会将__name__ equal to "firstmodel name"设置__name__ equal to "firstmodel name"




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

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

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




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

假设您有两个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是运行的主文件),那么只有代码被执行。




如果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__





Related