提问人:Devoted 提问时间:1/7/2009 最后编辑:Mateen UlhaqDevoted 更新时间:11/17/2023 访问量:4513125
if __name__ == “__main__”: do?
What does if __name__ == "__main__": do?
问:
这有什么作用,为什么要包含该语句?if
if __name__ == "__main__":
print("Hello, World!")
如果您试图关闭有人应该使用此成语而没有使用的问题,请考虑关闭 为什么 Python 在我导入模块时运行我的模块,以及如何停止它?对于某人根本没有调用任何函数,或者错误地期望将名为 main 的函数自动用作入口点的问题,请使用为什么启动 Python 脚本时 main() 函数不运行?脚本从哪里开始运行?.
答:
if __name__ == "__main__"
是使用类似 的命令从(例如)命令行运行脚本时运行的部分。python myscript.py
评论
helloworld.py
print("hello world")
python helloworld.py
if __name__ == "__main__"
python helloworld.py
if __name__ == "__main__"
helloworld.py
if __name__ == "__main__"
简答
它是样板代码,可防止用户在无意中意外调用脚本。以下是脚本中省略守卫时的一些常见问题:
如果在另一个脚本(例如)中导入无保护脚本,则后一个脚本将在导入时触发前者运行,并使用第二个脚本的命令行参数。这几乎总是一个错误。
import my_script_without_a_name_eq_main_guard
如果您在无防护脚本中有一个自定义类并将其保存到 pickle 文件中,则在另一个脚本中取消加密将触发无防护脚本的导入,并出现上一个项目符号中概述的相同问题。
长答案
为了更好地理解这很重要的原因和方式,我们需要退后一步来了解 Python 如何初始化脚本以及它如何与其模块导入机制交互。
每当 Python 解释器读取源文件时,它都会做两件事:
它设置了一些特殊变量,例如 ,然后
__name__
它执行在文件中找到的所有代码。
让我们看看它是如何工作的,以及它如何与您关于我们在 Python 脚本中经常看到的检查的问题相关联。__name__
代码示例
让我们使用一个稍微不同的代码示例来探索导入和脚本的工作原理。假设以下内容位于名为 的文件中。foo.py
# Suppose this is foo.py.
print("before import")
import math
print("before function_a")
def function_a():
print("Function A")
print("before function_b")
def function_b():
print("Function B {}".format(math.sqrt(100)))
print("before __name__ guard")
if __name__ == '__main__':
function_a()
function_b()
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
解释器将搜索您的文件(以及搜索其他一些变体),在执行该模块之前,它会将 import 语句中的名称分配给变量,即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"
执行模块的代码
设置特殊变量后,解释器执行模块中的所有代码,一次执行一条语句。您可能需要在代码示例的一侧打开另一个窗口,以便您可以按照此说明进行操作。
总是
它打印字符串(不带引号)。
"before import"
它加载模块并将其分配给名为 的变量。这相当于替换为以下内容(请注意,这是 Python 中的一个低级函数,它接受字符串并触发实际导入):
math
math
import math
__import__
# Find and load a module given its string name, "math",
# then assign it to a local variable called math.
math = __import__("math")
它打印字符串 。
"before function_a"
它执行该块,创建一个函数对象,然后将该函数对象分配给一个名为 的变量。
def
function_a
它打印字符串 。
"before function_b"
它执行第二个块,创建另一个函数对象,然后将其分配给名为 的变量。
def
function_b
它打印字符串 。
"before __name__ guard"
仅当您的模块是主程序时
- 如果你的模块是主程序,那么它会看到它确实被设置为,它调用两个函数,打印字符串和 .
__name__
"__main__"
"Function A"
"Function B 10.0"
仅当您的模块被另一个模块导入时
- (取而代之的是)如果你的模块不是主程序,而是由另一个模块导入的,那么它将是 ,而不是 ,它将跳过语句的主体。
__name__
"foo"
"__main__"
if
总是
- 在这两种情况下,它都会打印字符串。
"after __name__ guard"
总结
总而言之,以下是在这两种情况下打印的内容:
# What gets printed if foo is the main program
before import
before function_a
before function_b
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 function_a
before function_b
before __name__ guard
after __name__ guard
为什么它以这种方式工作?
你可能自然想知道为什么有人会想要这个。好吧,有时你想写一个文件,既可以被其他程序和/或模块用作模块,也可以作为主程序本身运行。例子:.py
你的模块是一个库,但你希望有一个脚本模式,在其中运行一些单元测试或演示。
您的模块仅用作主程序,但它有一些单元测试,测试框架通过导入脚本等文件并运行特殊的测试函数来工作。您不希望它仅仅因为它正在导入模块而尝试运行脚本。
.py
您的模块主要用作主程序,但它也为高级用户提供了程序员友好的 API。
除了这些例子之外,在 Python 中运行脚本只是设置一些神奇的变量并导入脚本,这很优雅。“运行”脚本是导入脚本模块的副作用。
发人深思的东西
问:我可以有多个检查块吗?答:这样做很奇怪,但语言不会阻止你。
__name__
假设以下内容位于 中。如果你在命令行上说会发生什么?为什么?
foo2.py
python foo2.py
# Suppose this is foo2.py.
import os, sys; sys.path.insert(0, os.path.dirname(__file__)) # needed for some interpreters
def function_a():
print("a1")
from foo2 import function_b
print("a2")
function_b()
print("a3")
def function_b():
print("b")
print("t1")
if __name__ == "__main__":
print("m1")
function_a()
print("m2")
print("t2")
- 现在,弄清楚会发生什么(删除了检查):
foo3.py
__name__
# Suppose this is foo3.py.
import os, sys; sys.path.insert(0, os.path.dirname(__file__)) # needed for some interpreters
def function_a():
print("a1")
from foo3 import function_b
print("a2")
function_b()
print("a3")
def function_b():
print("b")
print("t1")
print("m1")
function_a()
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")
评论
subprocess.run('foo_bar.py')
foo_bar
__name__ = '__main__'
foo_bar.py
__name__
subprocess
subprocess.run
subprocess.run
multiprocessing
__name__
当通过将脚本作为命令传递给 Python 解释器来运行脚本时,
python myscript.py
将执行缩进级别为 0 的所有代码。定义的函数和类是已定义的,但它们的代码都不会运行。与其他语言不同,没有自动运行的函数 - 该函数隐含了顶层的所有代码。main()
main()
在本例中,顶级代码是一个块。 是一个内置变量,其计算结果为当前模块的名称。但是,如果直接运行模块(如上所述),则设置为字符串 。因此,您可以通过测试来测试您的脚本是直接运行还是由其他内容导入if
__name__
myscript.py
__name__
"__main__"
if __name__ == "__main__":
...
如果将脚本导入到另一个模块中,则将导入其各种函数和类定义,并执行其顶级代码,但上述子句的当时正文中的代码将不会运行,因为不满足条件。作为基本示例,请考虑以下两个脚本: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__"
评论
if __name__ == "__main__":
创建以下两个文件:
# a.py
import b
# b.py
print("__name__ equals " + __name__)
if __name__ == '__main__':
print("if-statement was executed")
现在单独运行每个文件。
运行 python a.py
:
$ python a.py
__name__ equals b
执行时,它会导入模块。这会导致内部的所有代码运行。Python 在模块中设置为模块的名称 。a.py
b
b
globals()['__name__']
b
b
运行 python b.py
:
$ python b.py
__name__ equals __main__
if-statement was executed
当仅执行该文件时,Python 会在此文件中设置为 .因此,语句的计算结果为此时。b.py
globals()['__name__']
"__main__"
if
True
当从命令行调用 Python 文件时,它是特殊的。这通常用于调用“main()”函数或执行其他适当的启动代码,例如命令行参数处理。
它可以用几种方式编写。另一个是:
def some_function_for_instance_main():
dosomething()
__name__ == '__main__' and some_function_for_instance_main()
我并不是说你应该在生产代码中使用它,但它可以说明.if __name__ == '__main__'
它只是在 Python 文件中调用 main 函数的约定。
评论
and
and
and
if
and
or
x = input("what is your name? ") or "Nameless Person"
and
and
or
当我们的模块()中有某些语句时,我们希望在它作为main(未导入)运行时执行,我们可以将这些语句(测试用例,print语句)放在此块下。M.py
if
默认情况下(当模块作为 main 运行,而不是导入时),变量设置为 ,当它被导入时,变量将获得不同的值,很可能是模块的名称 ()。
这有助于将模块的不同变体一起运行,并分离它们的特定输入和输出语句,以及是否有任何测试用例。__name__
"__main__"
__name__
'M'
简而言之,使用此 ' ' 块来防止在导入模块时运行(某些)代码。if __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
do_important()
# do_important() # I must remember to uncomment to execute this!
然后,您必须记住是否注释掉了测试函数调用。而这种额外的复杂性意味着你很可能会忘记,使你的开发过程更加麻烦。
更好的方式
该变量指向 Python 解释器当前所在的命名空间。__name__
在导入的模块中,它是该模块的名称。
但是在主模块(或交互式 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()
评论
A Better Way
An Even Better Way
A Better Way
An Even Better Way
以交互方式运行 Python 时,会为局部变量分配值 。同样,当您从命令行执行 Python 模块时,而不是将其导入到另一个模块中,其属性将被分配值 ,而不是模块的实际名称。通过这种方式,模块可以查看自己的值,以确定它们的使用方式,无论是作为对另一个程序的支持还是作为从命令行执行的主应用程序。因此,以下习语在 Python 模块中很常见:__name__
__main__
__name__
__main__
__name__
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.
该怎么办?
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()
让我们以更抽象的方式看一下答案:
假设我们在以下位置有以下代码:x.py
...
<Block A>
if __name__ == '__main__':
<Block B>
...
块 A 和 B 在我们运行时运行。x.py
但是,当我们运行另一个模块时,只运行块 A(而不是 B),例如,在该模块中导入并从那里运行代码(例如,当调用函数时)。y.py
x.py
x.py
y.py
系统(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”。
希望这会有所帮助。
评论
if __name__ == "__main__":
基本上是顶级脚本环境,它指定了解释器(“我有最高优先级首先执行”)。
'__main__'
是执行顶级代码的作用域的名称。模块的设置为等于从标准输入、脚本或交互式提示读取时。__name__
'__main__'
if __name__ == "__main__":
# Execute only if run as a script
main()
考虑:
print __name__
上述的输出是 。__main__
if __name__ == "__main__":
print "direct method"
上述陈述是正确的,并打印了“直接方法”。假设如果他们在另一个类中导入了这个类,它不会打印“直接方法”,因为在导入时,它将设置 .__name__ equal to "first model name"
关于所讨论的代码的机制,即“如何”,这里有很多不同的看法,但对我来说,在我理解“为什么”之前,这些都没有意义。这对新程序员应该特别有帮助。
获取文件“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()
这段代码到底在做什么?
当你执行时,你.import 语句在导入时立即运行模块,因此 的操作在 's 的其余部分之前执行。一旦用完 ,它就会继续用 。xy.py
import ab
ab
xy
ab
xy
解释器跟踪哪些脚本正在使用 .当你运行一个脚本时 - 无论你给它起了什么名字 - 解释器都会调用它,使其成为运行外部脚本后返回的主脚本或“主”脚本。__name__
"__main__"
从此脚本调用的任何其他脚本都分配了其文件名作为其文件名(例如,)。因此,该行是解释器的测试,以确定它是否正在解释/解析最初执行的“主页”脚本,或者它是否暂时窥视另一个(外部)脚本。这使程序员可以灵活地使脚本在直接执行和外部调用时的行为有所不同。"__main__"
__name__
__name__ == "ab.py"
if __name__ == "__main__":
让我们逐步浏览上面的代码来了解正在发生的事情,首先关注未缩进的行及其在脚本中的显示顺序。请记住,函数 - 或 - 块在被调用之前不会自行执行任何操作。如果口译员喃喃自语,可能会说什么:def
- 将 xy.py 作为“home”文件打开;在变量中调用它。
"__main__"
__name__
- 导入并使用 .
__name__ == "ab.py"
- 哦,一个函数。我会记住的。
- 好的,功能;我刚刚学会了这一点。打印“ab 文件中的函数”。
a()
- 文件末尾;返回 !
"__main__"
- 哦,一个函数。我会记住的。
- 另一个。
- 功能;好的,打印“外围任务:可能在其他项目中有用”。
x()
- 这是怎麽?一个声明。好了,条件已经满足(变量已设置为 ),所以我将输入函数并打印“主函数:这是操作所在的地方”。
if
__name__
"__main__"
main()
底部的两行表示:“如果这是 or 'home' 脚本,请执行名为 ”.这就是为什么你会在顶部看到一个块,其中包含脚本功能的主流。"__main__"
main()
def main():
为什么要实现这个?
还记得我之前说过的关于进口语句吗?当您导入模块时,它不仅会“识别”它并等待进一步的指令 - 它实际上会运行脚本中包含的所有可执行操作。因此,将脚本的内容放入函数中可以有效地隔离它,将其隔离,以便在被另一个脚本导入时不会立即运行。main()
同样,也会有例外,但通常的做法是通常不会在外部调用。所以你可能想知道还有一件事:如果我们不调用,我们为什么要调用脚本?这是因为许多人使用独立函数来构建他们的脚本,这些函数被构建为独立于文件中的其余代码运行。然后,它们在脚本正文中的其他位置被调用。这让我想到了这一点:main()
main()
但是代码可以在没有它的情况下工作
是的,没错。可以从函数中未包含的内联脚本调用这些单独的函数。如果你已经习惯了(就像我一样,在我的编程早期学习阶段)构建完全符合你需求的内联脚本,如果你再次需要该操作,你会尝试再次弄清楚......好吧,你不习惯这种代码的内部结构,因为它的构建更复杂,而且阅读起来不那么直观。main()
但这是一个可能无法在外部调用其函数的脚本,因为如果它调用了它,它将立即开始计算和分配变量。如果你试图重用一个函数,你的新脚本很可能与旧脚本密切相关,以至于会出现冲突的变量。
在拆分独立函数时,您可以通过将以前的工作调用到另一个脚本中来重用它们。例如,“example.py”可以导入“xy.py”并调用 ,利用“xy.py”中的“x”函数。(也许是将给定文本字符串的第三个单词大写;从数字列表创建一个 NumPy 数组并将它们平方;或者去趋势化 3D 表面。可能性是无限的。x()
(顺便说一句,这个问题包含@kindall的答案,最终帮助我理解了——为什么,而不是如何。不幸的是,它被标记为这个的副本,我认为这是一个错误。
简单地说,是为每个脚本定义的变量,用于定义脚本是作为主模块运行还是作为导入模块运行。__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__
正如你所看到的,告诉我们哪个代码是“主”模块。
这很棒,因为您可以只编写代码,而不必担心像 C/C++ 那样的结构问题,如果文件没有实现“main”函数,那么它就不能编译为可执行文件,如果实现了,它就不能用作库。__name__
假设你编写了一个 Python 脚本,它做了一些伟大的事情,并且你实现了大量对其他目的有用的函数。如果我想使用它们,我只需导入您的脚本并在不执行程序的情况下使用它们(鉴于您的代码仅在上下文中执行)。而在 C/C++ 中,您必须将这些部分分成单独的模块,然后包含该文件。想象一下下面的情况;if __name__ == "__main__":
箭头是导入链接。对于三个模块,每个模块都尝试包含前面的模块代码,有六个文件(九个,包括实现文件)和五个链接。这使得很难将其他代码包含在 C 项目中,除非它被专门编译为库。现在想象一下 Python 的效果:
你编写一个模块,如果有人想使用你的代码,他们只需导入它,变量可以帮助将程序的可执行部分与库部分分开。__name__
评论
我认为最好用简单的话深入地分解答案:
__name__
:Python 中的每个模块都有一个称为 的特殊属性。
它是一个内置变量,用于返回模块的名称。__name__
__main__
:与其他编程语言一样,Python 也有一个执行入口点,即 main。 是执行顶级代码的作用域的名称。基本上,您有两种使用 Python 模块的方法:直接将其作为脚本运行,或导入它。当模块作为脚本运行时,其设置为 。'__main__'
__name__
__main__
因此,该属性的值设置为模块作为主程序运行时。否则,值设置为包含模块的名称。__name__
__main__
__name__
您可以将文件用作脚本和可导入模块。
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
考虑:
if __name__ == "__main__":
main()
它检查 Python 脚本的属性是否为 。换句话说,如果程序本身被执行,则属性将是 ,因此程序将被执行(在本例中为函数)。__name__
"__main__"
__main__
main()
但是,如果你的 Python 脚本被模块使用,则语句之外的任何代码都将被执行,因此仅用于检查程序是否用作模块,从而决定是否运行代码。if
if __name__ == "__main__"
原因
if __name__ == "__main__":
main()
主要是为了避免直接导入代码而产生的导入锁定问题。如果你的文件是直接调用的(就是这种情况),你想运行,但如果你的代码是导入的,那么导入器必须从真正的主模块输入你的代码,以避免导入锁定问题。main()
__name__ == "__main__"
副作用是,您会自动登录到支持多个入口点的方法。您可以使用它作为入口点运行程序,但您不必这样做。虽然预期,但其他工具使用备用入口点。例如,要将文件作为进程运行,请定义一个函数而不是 .就像 一样,导入您的代码,因此您不希望它在导入时执行任何操作(因为导入锁定问题)。main()
setup.py
main()
gunicorn
app()
main()
setup.py
gunicorn
创建一个文件,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
在解释 if __name__ == '__main__'
之前,重要的是要了解 __name__
是什么以及它的作用。
什么?__name__
__name__
是一个 DunderAlias - 可以被认为是一个全局变量(可从模块访问),其工作方式与 global
类似。
它是一个字符串(如上所述的全局),如 (yielding ) 所示,并且是 Python 3 和 Python 2 版本的内置标准。type(__name__)
<class 'str'>
哪里
它不仅可以在脚本中使用,还可以在解释器和模块/包中找到。
译员:
>>> print(__name__)
__main__
>>>
脚本:
test_file.py:
print(__name__)
导致__main__
模块或封装:
somefile.py:
def somefunction():
print(__name__)
test_file.py:
import somefile
somefile.somefunction()
导致somefile
请注意,在包或模块中使用时,采用文件的名称。没有给出实际模块或包路径的路径,但有自己的 DunderAlias ,允许这样做。__name__
__file__
您应该看到,其中,主文件(或程序)将始终返回,如果它是模块/包,或者运行其他 Python 脚本的任何内容,将返回它源自的文件的名称。__name__
__main__
实践
作为一个变量意味着它的值可以被覆盖(“can”并不意味着“应该”),覆盖 的值将导致缺乏可读性。所以无论出于何种原因,都不要这样做。如果需要变量,请定义一个新变量。__name__
始终假定 的值为 to be 或文件的名称。再次更改此默认值将导致更多的混淆,以为它会做得很好,从而导致进一步的问题。__name__
__main__
例:
>>> __name__ = 'Horrify' # Change default from __main__
>>> if __name__ == 'Horrify': print(__name__)
...
>>> else: print('Not Horrify')
...
Horrify
>>>
通常认为在脚本中包含 是良好做法。if __name__ == '__main__'
现在回答: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
您还可以使用它在包和模块上提供可运行的帮助函数/实用程序,而无需精心使用库。
它还允许模块作为主脚本从命令行运行,这也非常有用。
我们经常看到。__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__
所有的答案都几乎解释了功能。但我将举一个例子来说明它的用法,这可能有助于进一步澄清这个概念。
假设您有两个 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
如果此 .py 文件由其他 .py 文件导入,则不会执行该语句下的代码。if
如果此.py由在shell下运行,或在Windows中双击。语句下的代码将被执行。python this_py.py
if
它通常是为测试而编写的。
简而言之,您需要了解以下几点:
import a
action 实际上运行了所有可以运行的内容,这意味着a.py
a.py
由于第 1 点,您可能不希望在导入它时运行所有内容
a.py
为了解决第 2 点中的问题,Python 允许您使用条件检查
__name__
是所有模块中的隐式变量:.py
- 当 ED 时,模块的值设置为其文件名”
a.py
import
__name__
a.py
a
" - 当直接使用 “” 运行时,的值设置为字符串
a.py
python a.py
__name__
__main__
- 根据 Python 为每个模块设置变量的机制,你知道如何实现第 3 点吗?答案很简单,对吧?使用 if 条件:
__name__
if __name__ == "__main__": // do A
- 然后将运行该部件
python a.py
// do A
- 并将跳过该部分
import a
// do A
- 你甚至可以根据你的功能需要放,但很少这样做
__name__ == "a"
Python 的特别之处在于第 4 点!剩下的只是基本逻辑。
在这个页面上的答案中,我一直在阅读很多。我想说,如果你知道这件事,你肯定会理解这些答案,否则,你仍然感到困惑。
这个答案是为学习 Python 的 Java 程序员准备的。 每个 Java 文件通常包含一个公共类。可以通过两种方式使用该类:
从其他文件调用该类。您只需要将其导入调用程序即可。
出于测试目的,单独运行类。
对于后一种情况,该类应包含一个公共静态 void main() 方法。在Python中,此目的由全局定义的标签提供。'__main__'
简单地说,它是运行文件的入口点,就像 C 编程语言中的函数一样。main
评论
if __name__ == "__main__"
Python 中的每个模块都有一个名为 .attribute 的值是模块直接运行时的值,如 。否则(就像你说的一样),的值是模块的名称。__name__
__name__
__main__
python my_module.py
import my_module
__name__
简单说明一下。
脚本 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
现在假设我们从另一个脚本调用上述脚本:
脚本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
因此,以上是不言自明的,当您从另一个脚本调用 test 时,if loop in 将不会执行。__name__
test.py
如果 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()
运行此脚本时,它会打印:
you can see me
a
如果导入此文件,将 A 导入文件 B,然后执行文件 B
,则在文件
A
中变为 False,因此它会打印:if __name__ == "__main__"
You can't see me
b
你可以用这个简单的例子来检查特殊变量:__name__
创建 file1.py
if __name__ == "__main__":
print("file1 is being run directly")
else:
print("file1 is being imported")
创建 *file2。皮
import file1 as f1
print("__name__ from file1: {}".format(f1.__name__))
print("__name__ from file2: {}".format(__name__))
if __name__ == "__main__":
print("file2 is being run directly")
else:
print("file2 is being imported")
执行 file2.py
输出:
file1 is being imported
__name__ from file1: file1
__name__ from file2: __main__
file2 is being run directly
只有当模块作为脚本调用时,才会执行下面的代码。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()
my_test_module
第二种可能性:将my_test_module.py
作为脚本调用
现在,如果作为 Python 脚本运行,则将执行这两个语句:my_test_module.py
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'
有关更全面的解释,您可以阅读 如果 __name__ == '__main__'
在 Python 中做什么。
Python main 函数是任何程序的起点。程序运行时,Python 解释器按顺序运行代码。main 函数仅在作为 Python 程序运行时执行...
def main():
print("I am in the function")
print("I am out of the function")
运行脚本时显示:
I am out of the function
而不是代码“我在函数中”。
这是因为我们没有声明调用函数 “if__name__== ”main”。
如果您从它使用:
def main():
print("I am in the function")
if __name__ == "__main__":
main()
print("I am out of the function")
输出等于
I am in the function
I am out of the function
在 Python 中,允许您将 Python 文件作为可重用模块或独立程序运行。if__name__== "__main__"
当 Python 解释器读取源文件时,它将执行在其中找到的所有代码。
当Python将“源文件”作为主程序运行时,它会将特殊变量设置为具有值。__name__
"__main__"
当您执行 main 函数时,它将读取检查是否等于 的语句。if
__name__
__main__
评论
Python 中的每个模块都有一个称为 的特殊属性。该属性的值设置为当模块作为主程序执行时(例如,运行 )。__name__
__name__
'__main__'
python foo.py
否则,值将设置为从中调用它的模块的名称。__name__
评论
简单来说:
只有当您的 Python 文件被执行为if __name__ == "__main__":
python example1.py
但是,如果您希望将 Python 文件作为模块导入以使用另一个 Python 文件,请说 ,下面的代码将不会运行或产生任何影响。example1.py
example2.py
if __name__ == "__main__":
if __name__ == "__main__"
意味着如果您像 一样正常运行 Python 文件,它会将特殊变量分配给 。python foo.py
__name__
"__main__"
但是,如果您像“import foo”一样导入文件,它将分配给并且不会运行该函数。__name__
"foo"
执行 Python 文件时,它会创建许多特殊变量,例如 .该变量保存文件的名称。你的问题的答案是__name__
__name__
if __name__ == "__main__":
# Do something
这意味着,如果正在执行的文件的名称作为源文件而不是模块运行,那么它将运行其中的代码。这可以通过一个简单的例子来证明。创建两个 Python 文件,然后 .然后在 中,键入以下内容:foo.py
second.py
foo.py
if __name__ == "__main__":
print("file is not imported")
else:
print("file is imported")
在 中,键入以下内容:second.py
import foo
if foo.__name__ == "__main__":
print("file is not imported")
else:
print("file is imported")
除此之外,如果您要这样做,那么它将打印 .为什么?print(__name__)
__main__
因为该文件作为主要源运行,如果你这样做,它将打印 foo,因为变量的默认值是文件的名称,默认情况下我的意思是你也可以更改它。为此,只需转到文件并执行以下操作:.然后,当您运行该文件时,例如,print(foo.__name__)
__name__
foo.py
__name__ = "name"
__name__ = "Hello, World!"
print(__name__)
则输出为:
Hello, World!
执行模块(源文件)时,if 条件检查是直接调用模块还是从其他源文件调用模块。这里直接表示不导入。
如果直接调用它来执行,则模块名称设置为“main”,然后将执行 if 块中的代码。
评论
假设我在维基百科上编写了用于网页抓取的函数和类。当然,这可能不是一个很好的例子。
我想在另一个程序中使用这些函数而不重写它。
好吧,我导入它们,但在该文件的末尾
我把__name__ == '__main__'
当我们一个模块时,它里面的所有代码都是从头到尾执行的。但是当它达到条件时,它不会运行 func、func2 等,这就是维基百科。import
__scrape__
好吧,在全局范围内,为当前程序定义了 Python。__name__
'__main__'
当我们一个模块时,它被定义为我们当前程序名称空间中的变量
目前的程序是:import
__name__
'__main__'
文件 test.py
def func():
# Do something
pass
def func2():
# Do something
pass
print('The program name is set to ', globals()['__name__'])
if __name__=='__main__':
# In the current program, __name__ is equal to '__main__'
func('https://www.wikipedia.org')
func2('https://www.wikipedia.org')
# Or do more jobs
import test1
print('inside of current program')
print('name is current program', __name__)
print(globals()['test1'])
test1.func('another site')
test1.func2('another site')
输出
inside of test 1
name of program is set to test1
end of module
inside of current
__main__
<module 'test1' from 'C:\\users\\ir\\appdata\\local\\programs\\python\\python38\\lib\\test1.py'>
评论
如果你是一个初学者,你现在唯一需要的答案可能是这个代码对于一个简单的脚本是不必要的。它仅在您希望能够编写脚本(或等;有关其他一些非初学者方案,请参阅此处的其他答案)时才有用。import
unpickle
换言之,守卫是一种向其他代码隐藏代码的机制。如果你没有具体的理由来隐藏某些东西,不要:如果你不需要隐藏一些代码,不要把它放在这个守卫后面,如果你这样做了,请尽可能少地隐藏。if __name__
import
更详细地说,假设你有一个简单的脚本(改编自这个答案):fib.py
# XXX FIXME: useless (see below)
if __name__ == "__main__":
n = int(input('Write a number: '))
a, b = 0, 1
while b < n:
a, b = b, a+b
print('Fibonacci number %i: %i' % (n, b))
现在,如果您只是运行它就可以正常工作。但会一直处于这种情况,所以条件其实是不必要的。脚本可以简化为仅python fib.py
__name__
"__main__"
n = int(input('Write a number: '))
a, b = 0, 1
while b < n:
a, b = b, a+b
print('Fibonacci number %i: %i' % (n, b))
现在,你仍然不能使用新版本,但如果你一开始就不打算这样做,这个版本实际上更好,因为它更简单、更清晰。import fib
如果您确实希望能够 ,第一个版本也是无用的,因为有用的代码位于一个部分中,当您该文件时不会运行(在这种情况下不会)。在这种情况下,正确的设计是重构代码,以便有用的部分位于一个函数中,您可以在编辑后在需要时运行它。import fib
import
__name__
"__main__"
import
def main():
n = int(input('Write a number: '))
a, b = 0, 1
while b < n:
a, b = b, a+b
print('Fibonacci number %i: %i' % (n, b))
if __name__ == "__main__":
main()
现在,如果 ,则不会执行对 的调用;但是当你跑步时,它会的。import fib
main()
python fib.py
实际上,更好的设计仍然是将可重用的部分(实际计算)与用户可见的输入/输出隔离开来:
def fibn(n: int) -> int:
a, b = 0, 1
while b < n:
a, b = b, a+b
return b
def main() -> None:
n = int(input('Write a number: '))
print('Fibonacci number %i: %i' % (n, fibn(n)))
if __name__ == "__main__":
main()
现在,您可以从执行此操作的代码中调用该函数。from fib import fibn
fibn()
import
(我调用该函数只是为了更清楚地说明此示例中的内容。在现实生活中,你可能会这样称呼它并做。fibn()
fib()
from fib import fib
注意更加模块化和可重复使用的设计;该函数包含实际计算,但不包含用户界面部分;讨厌的交互式 I/O 被分离到函数中,以便您可以绕过它(当然,如果您愿意,也可以调用它)。fibn
main
回到问题中的代码,我同样会将代码从 移动到函数中,以便调用者可以根据需要调用该函数。if
def 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__":
main()
这会更改变量的范围;如果周围的代码需要访问它,则需要创建它(或者,也许更好的是,重构为 ,并让调用方在其自己的局部变量中捕获值)。lock
global
main
return lock
(与C语言不同,这个名字对Python没有特定的含义;但将其用作将要运行的事物的名称是一种常见的约定。你仍然必须实际显式地调用它,比如,不像在 C 中。main
main()
评论
input
n: int
-> int
F(0)
简单的答案是,如果将代码导入到另一个文件中,则在 if name == “main”: 下编写的代码将不会执行。
评论
只有你需要知道的事实
这个问题的其他答案太长了。实际的机制非常简单,只有两个基本事实:
纯 Python 模块始终使用设置为字符串的变量创建。
__name__
"__main__"
导入模块的副作用是将变量更改为不带扩展名的基本文件名。
__name__
.py
如何使用这些信息
人们写信来测试模块是否已导入。__name__ == '__main__'
在导入时,通常会有一些不应运行的代码:测试代码、一次性使用代码、命令行前端或 Web 服务器前端。
这个想法是,运行模块的人直接希望这些操作发生,但导入模块的人只想直接访问函数、类和变量。
从其他答案中可以看出,人们似乎可以无休止地谈论这个话题,但这确实是一件简单的事情,很容易掌握。Python 教程在大约两分钟的阅读中介绍了这一点。不要让其他答案因过度解释而淹没你:-)
当您的某些代码具有此条件时,它将返回(在导入的代码中),但将返回将要运行的代码。import
False
True
评论
if __name__ == “__main__”:
防止在导入文件时运行不需要的代码。
例如,这是 test1.py 没有
if __name__ == “__main__”:
:
# "test1.py"
def hello()
print("Hello")
hello()
test2.py
只导入 test1.py
:
# "test2.py"
import test1 # Here
然后,在运行 test2.py
时,会打印一个 Hello
,因为 test1.py
中不需要的代码 hello()
也会运行:
python test2.py
Hello
当然,你可以在 test2.py
中调用 test1.hello():
# "test2.py"
import test1
test1.hello() # Here
然后,在运行 test2
时,会打印两个 Hello
:
python test2.py
Hello
Hello
现在,添加 if __name__ == “__main__”
: test1.py
并将 hello()
放在它下面:
# "test1.py"
def hello()
print("Hello")
if __name__ == "__main__":
hello()
而且,这是 test2.py
:
# "test2.py"
import test1
test1.hello()
然后,在运行 test2.py
时,只打印一个 Hello
,因为 if __name__ == “__main__”:
阻止在导入
test1.py
时运行不需要的代码 hello(test2.py
):
python test2.py
Hello
此外,test1.py
是否有 if __name__ == “__main__”
: 或否:
# "test1.py"
def hello()
print("Hello")
if __name__ == "__main__":
hello()
# "test1.py"
def hello()
print("Hello")
hello()
运行 test1.py
时,One Hello
会正确打印:
python test1.py
Hello
If __name__=='__main__'
然后我们可以选择直接运行脚本如果脚本不包含(或任何其他名称),则无法直接运行该脚本
if __name__ == '__main__'
除了已经提供的信息之外,该技术还是一种很好的方法,可以确保你的 和 脚本在你不小心用 而不是 (或 ) 调用它们时仍然运行。下面是一个示例:if __name__ == "__main__":
pytest
unittest
python
pytest
python -m unittest
def test_assert():
assert 1 + 2 == 3
if __name__ == "__main__":
import pytest
pytest.main([__file__])
现在,无论使用 或 调用它,您的测试都将运行。版本如下:pytest
python
unittest
import unittest
class Tests(unittest.TestCase):
def test_assert(self):
self.assertTrue(1 + 2 == 3)
if __name__ == "__main__":
unittest.main()
然后,脚本在调用中的运行方式与在调用中的运行方式相同。python
python -m unittest
现在,如果您还想确保所有参数在调用时都会被传递给怎么办?或者,如果您还想包含其他参数怎么办?下面是如何执行此操作的示例:pytest
python
def test_assert():
assert 1 + 2 == 3
if __name__ == "__main__":
from pytest import main
from sys import argv
main([*argv, "-s"])
现在,你的效果与 等相同。这是确保脚本仍按预期运行的好方法,即使没有与预期或调用一起运行。python -v --html=report.html
pytest -v --html=report.html
pytest
python -m unittest
在项目中执行以下操作。
创建一个 python 文件,然后简单地打印 .
运行此 python 文件__name__
现在,将此 python 文件导入另一个 python 文件。请勿触摸打印语句。__name__
导入后,仍将执行。print(__name__)
首先,输出将是 。但在第二种情况下,输出会有所不同(根据 python 文件的名称)。__main__
因此,如果添加 if 检查,则如果 python 文件正在运行而不作为独立脚本导入,它将返回 True。但是,如果它正在导入,则其计算结果为 False。你为什么需要这一切?if __name__ == "__main__"
也许你的 python 文件是基于类的或基于函数的。您可能希望在不同的 python 文件中重用这些类或函数。但是,您可能不希望执行 python 脚本,该脚本将在 python 脚本作为独立脚本执行时执行。
因此,请确保在几乎每个 python 文件中添加它。
评论
if __name__