Dev*_*ted 5545 python program-entry-point idioms namespaces python-module
怎么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))
Run Code Online (Sandbox Code Playgroud)
Mr *_*ooz 6006
每当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")
Run Code Online (Sandbox Code Playgroud)
当Python interpeter读取源文件时,它首先定义一些特殊变量.在这种情况下,我们关心__name__
变量.
当您的模块是主程序时
如果您正在运行模块(源文件)作为主程序,例如
python foo.py
Run Code Online (Sandbox Code Playgroud)
解释器将硬编码字符串赋值"__main__"
给__name__
变量,即
# It's as if the interpreter inserts this at the top
# of your module when run as the main program.
__name__ = "__main__"
Run Code Online (Sandbox Code Playgroud)
当您的模块被另一个导入时
另一方面,假设某些其他模块是主程序,它会导入您的模块.这意味着在主程序或主程序导入的其他模块中有这样的声明:
# Suppose this is in some other main program.
import foo
Run Code Online (Sandbox Code Playgroud)
在这种情况下,解释器将查看模块的文件名foo.py
,剥离.py
,并将该字符串分配给模块的__name__
变量,即
# It's as if the interpreter inserts this at the top
# of your module when it's imported from another module.
__name__ = "foo"
Run Code Online (Sandbox Code Playgroud)
设置特殊变量后,解释器将执行模块中的所有代码,一次执行一个语句.您可能希望使用代码示例打开另一个窗口,以便您可以按照此说明进行操作.
总是
它打印字符串"before import"
(不带引号).
它加载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")
Run Code Online (Sandbox Code Playgroud)
它打印字符串"before functionA"
.
它执行def
块,创建一个函数对象,然后将该函数对象分配给一个名为的变量functionA
.
它打印字符串"before functionB"
.
它执行第二个def
块,创建另一个函数对象,然后将其分配给一个名为的变量functionB
.
它打印字符串"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 functionA
before functionB
before __name__ guard
Function A
Function B 10.0
after __name__ guard
Run Code Online (Sandbox Code Playgroud)
# What gets printed if foo is imported as a regular module
before import
before functionA
before functionB
before __name__ guard
after __name__ guard
Run Code Online (Sandbox Code Playgroud)
你可能自然想知道为什么有人想要这个.好吧,有时你想要编写一个.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")
Run Code Online (Sandbox Code Playgroud)
__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")
Run Code Online (Sandbox Code Playgroud)
# Suppose this is in foo4.py
__name__ = "__main__"
def bar():
print("bar")
print("before __name__ guard")
if __name__ == "__main__":
bar()
print("after __name__ guard")
Run Code Online (Sandbox Code Playgroud)
Ada*_*eld 1709
通过将脚本作为命令传递给Python解释器来运行脚本时,
python myscript.py
Run Code Online (Sandbox Code Playgroud)
压缩级别为0的所有代码都会被执行.已定义的函数和类已定义,但它们的代码都不会运行.与其他语言不同,没有main()
自动运行的main()
功能- 该功能隐含在顶层的所有代码中.
在这种情况下,顶级代码是一个if
块. __name__
是一个内置变量,它计算当前模块的名称.但是,如果直接运行模块(myscript.py
如上所述),则将__name__
其设置为字符串"__main__"
.因此,您可以测试脚本是直接运行还是通过测试由其他内容导入
if __name__ == "__main__":
...
Run Code Online (Sandbox Code Playgroud)
如果您的脚本被导入到另一个模块中,它的各种函数和类定义将被导入并且它的顶级代码将被执行,但是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")
Run Code Online (Sandbox Code Playgroud)
# 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")
Run Code Online (Sandbox Code Playgroud)
现在,如果你调用解释器
python one.py
Run Code Online (Sandbox Code Playgroud)
输出将是
top-level in one.py
one.py is being run directly
Run Code Online (Sandbox Code Playgroud)
如果你two.py
改为:
python two.py
Run Code Online (Sandbox Code Playgroud)
你得到
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
Run Code Online (Sandbox Code Playgroud)
因此,当模块one
加载时,它__name__
等于"one"
而不是"__main__"
.
pi.*_*pi. 686
__name__
变量(imho)的最简单解释如下:
创建以下文件.
# a.py
import b
Run Code Online (Sandbox Code Playgroud)
和
# b.py
print "Hello World from %s!" % __name__
if __name__ == '__main__':
print "Hello World again from %s!" % __name__
Run Code Online (Sandbox Code Playgroud)
运行它们会得到这个输出:
$ python a.py
Hello World from b!
Run Code Online (Sandbox Code Playgroud)
如您所见,在导入模块时,Python会globals()['__name__']
在此模块中设置模块的名称.此外,导入时,模块中的所有代码都在运行.由于if
语句评估False
此部分未执行.
$ python b.py
Hello World from __main__!
Hello World again from __main__!
Run Code Online (Sandbox Code Playgroud)
如您所见,当执行文件时,Python会globals()['__name__']
在此文件中设置"__main__"
.这一次,if
语句评估True
并正在运行.
Aar*_*all 494
怎么
if __name__ == "__main__":
办?
概述基础知识:
全局变量,__name__
在作为程序入口点的模块中,是'__main__'
.否则,它是您导入模块的名称.
因此,if
只有当模块是程序的入口点时,块下的代码才会运行.
它允许模块中的代码可由其他模块导入,而无需在导入时执行下面的代码块.
我们为什么需要这个?
假设您正在编写旨在用作模块的Python脚本:
def do_important():
"""This function does something very important"""
Run Code Online (Sandbox Code Playgroud)
您可以通过将函数调用添加到底部来测试模块:
do_important()
Run Code Online (Sandbox Code Playgroud)
并运行它(在命令提示符下),例如:
~$ python important.py
Run Code Online (Sandbox Code Playgroud)
但是,如果要将模块导入另一个脚本:
import important
Run Code Online (Sandbox Code Playgroud)
在导入时,do_important
将调用该函数,因此您可能会do_important()
在底部注释掉函数调用.
# do_important() # I must remember to uncomment to execute this!
Run Code Online (Sandbox Code Playgroud)
然后你必须记住你是否已经注释掉你的测试函数调用.而这种额外的复杂性意味着您可能会忘记,使您的开发过程更加麻烦.
该__name__
变量指向Python解释器恰好在哪里的命名空间.
在导入的模块中,它是该模块的名称.
但是在主模块(或交互式Python会话,即解释器的Read,Eval,Print Loop或REPL)中,您运行的是其中的所有内容"__main__"
.
所以如果你在执行前检查:
if __name__ == "__main__":
do_important()
Run Code Online (Sandbox Code Playgroud)
通过上述操作,您的代码将仅在您将其作为主模块运行时执行(或有意从其他脚本调用它).
不过,有一种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()
Run Code Online (Sandbox Code Playgroud)
我们现在有一个最终函数用于我们的模块结束,如果我们将模块作为主模块运行,它将运行.
它将允许将模块及其函数和类导入到其他脚本中而无需运行该main
函数,并且还允许在从不同'__main__'
模块运行时调用模块(及其函数和类),即
import important
important.main()
Run Code Online (Sandbox Code Playgroud)
这个习惯用法也可以在Python文档的__main__
模块解释中找到.该文字指出:
此模块表示解释程序主程序执行的(否则为匿名)作用域 - 从标准输入,脚本文件或交互式提示读取命令.正是在这种环境中,惯用的"条件脚本"节导致脚本运行:
Run Code Online (Sandbox Code Playgroud)if __name__ == '__main__': main()
Har*_*mbe 119
if __name__ == "__main__"
是使用类似命令从(例如)命令行运行脚本时运行的部分python myscript.py
.
Aar*_*all 75
怎么
if __name__ == "__main__":
办?
__name__
是一个全局变量(在Python中,全局实际上意味着在模块级别上),它存在于所有名称空间中.它通常是模块的名称(作为str
类型).
然而,作为唯一的特殊情况,无论你在哪个Python进程中运行,如在mycode.py中:
python mycode.py
Run Code Online (Sandbox Code Playgroud)
否则匿名全局命名空间被赋值'__main__'
给它的值__name__
.
因此,包括最后一行
if __name__ == '__main__':
main()
Run Code Online (Sandbox Code Playgroud)
将导致脚本的唯一定义main
函数运行.
使用此构造的另一个好处是:您还可以将代码作为模块导入另一个脚本中,然后在程序决定时运行main函数:
import mycode
# ... any amount of other code
mycode.main()
Run Code Online (Sandbox Code Playgroud)
joe*_*hoj 65
这里有很多不同的关于代码的机制,"如何",但对我来说,除非我理解"为什么",否则它们都没有意义.这应该对新程序员特别有用.
拿文件"ab.py":
def a():
print('A function in ab file');
a()
Run Code Online (Sandbox Code Playgroud)
第二个文件"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()
Run Code Online (Sandbox Code Playgroud)
这段代码到底在做什么?
当你执行时xy.py
,你import ab
.import语句在导入时立即运行模块,因此ab
操作在其余部分之前执行xy
.一旦完成ab
,它继续xy
.
解释器跟踪正在运行的脚本__name__
.当您运行脚本时 - 无论您将其命名为什么 - 解释器都会调用它"__main__"
,使其成为运行外部脚本后返回的主或"主"脚本.
从此"__main__"
脚本调用的任何其他脚本都将其文件名指定为其__name__
(例如,__name__ == "ab.py"
).因此,该行if __name__ == "__main__":
是解释器的测试,用于确定它是否正在解释/解析最初执行的"主页"脚本,或者它是否暂时窥视另一个(外部)脚本.这为程序员提供了灵活性,使脚本的行为不同,如果它直接执行而不是外部调用.
让我们逐步执行上面的代码来了解发生了什么,首先关注的是未缩进的行以及它们在脚本中出现的顺序.请记住,函数 - 或def
- 块在调用之前不会自行执行任何操作.如果嘟to自己,翻译可能会说些什么:
"__main__"
在__name__
变量中调用它.__name__ == "ab.py"
.a()
; 我刚学会了这个.打印' ab文件中的函数 '."__main__"
!x()
; 好的,打印' 外围任务:可能在其他项目中很有用 '.if
声明.好吧,条件已经满足(变量__name__
已经设置为"__main__"
),所以我将进入main()
函数并打印' main函数:这是动作的位置 '.底部两行表示:"如果这是"__main__"
'或'home'脚本,则执行名为main()
" 的函数.这就是为什么你会看到一个def main():
块顶部,其中包含脚本功能的主要流程.
为什么实现这个?
还记得我之前说的关于import语句的内容吗?导入模块时,它不仅"识别"它并等待进一步的指示 - 它实际上运行脚本中包含的所有可执行操作.因此,将脚本的内容放入main()
函数中会有效隔离它,将其置于隔离状态,以便在由另一个脚本导入时不会立即运行.
同样,会有例外,但通常的做法是main()
通常不会被外部调用.所以你可能想知道另一件事:如果我们不打电话main()
,为什么我们要调用脚本呢?这是因为许多人使用独立函数构建脚本,这些函数构建为独立于文件中的其余代码运行.然后他们被称为剧本正文中的其他地方.这让我想到了这个:
但代码在没有它的情况下工作
恩,那就对了.可以从不包含在main()
函数内的内联脚本调用这些单独的函数.如果您已经习惯(就像我在编程的早期学习阶段一样)构建完全符合您需要的内联脚本,并且如果您再次需要该操作,您将尝试再次弄清楚它.好吧,你不习惯你的代码的这种内部结构,因为它的构建更复杂,而且阅读不那么直观.
但这是一个可能无法在外部调用其函数的脚本,因为如果这样做,它会立即开始计算和分配变量.如果您正在尝试重新使用某个函数,那么您的新脚本可能与旧版本密切相关,因为存在冲突的变量.
在拆分独立函数时,您可以通过将它们调用到另一个脚本中来重用以前的工作.例如,"example.py"可能导入"xy.py"并调用x()
,使用"xy.py" 中的"x"函数.(也许它正在大写给定文本字符串的第三个单词;从数字列表创建NumPy数组并对它们进行平方;或者去除3D表面的去除.可能性是无限的.)
(顺便说一句,这个问题包含@kindall终于让我明白一个答案-其所以然,而不是如何不幸的是它被标记为与重复这一个,我认为这是一个错误)
Nab*_*med 48
当我们的module(M.py
)中存在某些语句时,我们希望在它作为main(未导入)运行时执行,我们可以将这些语句(测试用例,打印语句)放在此if
块下.
默认情况下(当模块作为main运行,而不是导入时)__name__
变量被设置为"__main__"
,当它被导入时,__name__
变量将获得不同的值,最可能是模块的名称('M'
).这有助于将模块的不同变体一起运行,并将它们的特定输入和输出语句分开,以及是否存在任何测试用例.
简而言之,使用此" if __name__ == "main"
块"可以防止(某些)代码在导入模块时运行.
red*_*dit 40
简而言之,__name__
是为每个脚本定义的变量,用于定义脚本是作为主模块运行还是作为导入模块运行.
所以,如果我们有两个脚本;
#script1.py
print "Script 1's name: {}".format(__name__)
Run Code Online (Sandbox Code Playgroud)
和
#script2.py
import script1
print "Script 2's name: {}".format(__name__)
Run Code Online (Sandbox Code Playgroud)
执行script1的输出是
Script 1's name: __main__
Run Code Online (Sandbox Code Playgroud)
执行脚本2的输出是:
Script1's name is script1
Script 2's name: __main__
Run Code Online (Sandbox Code Playgroud)
如您所见,__name__
告诉我们哪个代码是"主要"模块.这很好,因为你可以只编写代码而不必担心C/C++中的结构问题,如果文件没有实现'main'函数那么它就不能被编译成可执行文件,如果是的话,它不能用作库.
假设您编写了一个Python脚本,它可以执行一些非常棒的操作,并且您可以实现一系列对其他用途有用的函数.如果我想使用它们,我可以导入你的脚本并使用它们而不执行你的程序(假设你的代码只在if __name__ == "__main__":
上下文中执行 ).而在C/C++中,您必须将这些部分分成一个单独的模块,然后包含该文件.想象下面的情况;
箭头是导入链接.对于每个试图包含前面的模块代码的三个模块,有六个文件(九个,计算实现文件)和五个链接.这使得很难将其他代码包含到C项目中,除非它专门编译为库.现在想象一下Python:
你编写了一个模块,如果有人想要使用你的代码,他们只需导入它,__name__
变量就可以帮助将程序的可执行部分与库部分分开.
Gio*_*ous 39
The code under if __name__ == '__main__':
will be executed only if the module is invoked as a script.
As an example consider the following module 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')
Run Code Online (Sandbox Code Playgroud)
1st possibility: Import my_test_module.py
in another module
# main.py
import my_test_module
if __name__ == '__main__':
print('Hello from main.py')
Run Code Online (Sandbox Code Playgroud)
Now if you invoke main.py
:
python main.py
>> 'This is going to be printed out, no matter what'
>> 'Hello from main.py'
Run Code Online (Sandbox Code Playgroud)
Note that only the top-level print()
statement in my_test_module
is executed.
2nd possibility: Invoke my_test_module.py
as a script
Now if you run my_test_module.py
as a Python script, both print()
statements will be exectued:
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'
Run Code Online (Sandbox Code Playgroud)
For a more comprehensive explanation you can read What does if __name__ == '__main__'
do in Python.
Ali*_*isa 37
让我们以更抽象的方式看待答案:
假设我们在x.py中有这个代码:
...
<Block A>
if __name__ == '__main__':
<Block B>
...
Run Code Online (Sandbox Code Playgroud)
当我们运行"x.py"时,块A和B运行.
但是当我们运行另一个模块时运行块A(而不是B),例如"y.py",其中导入了xy并且从那里运行代码(就像"x.py"中的函数是从y.py调用.
Zai*_*ain 33
以交互方式运行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.
Run Code Online (Sandbox Code Playgroud)
Lar*_*rry 31
考虑:
if __name__ == "__main__":
main()
Run Code Online (Sandbox Code Playgroud)
它检查__name__
Python脚本的属性是否为"__main__"
.换句话说,如果程序本身被执行,那么属性将被执行,__main__
因此程序将被执行(在这种情况下是main()
函数).
但是,如果模块使用Python脚本,if
则会执行语句之外的任何代码,因此if \__name__ == "\__main__"
仅用于检查程序是否用作模块,因此决定是否运行代码.
Sim*_*mon 27
在解释任何事情之前,了解if __name__ == '__main__'
它的作用和作用非常重要__name__
.
什么是
__name__
?
__name__
是DunderAlias - 可以被认为是一个全局变量(可从模块访问)并以类似的方式工作global
.
它是一个字符串(如上所述的全局),由type(__name__)
(屈服<class 'str'>
)表示,并且是Python 3和Python 2版本的内置标准.
哪里:
它不仅可以在脚本中使用,还可以在解释器和模块/包中找到.
解释:
>>> print(__name__)
__main__
>>>
Run Code Online (Sandbox Code Playgroud)
脚本:
test_file.py:
print(__name__)
Run Code Online (Sandbox Code Playgroud)
导致 __main__
模块或包装:
somefile.py:
def somefunction():
print(__name__)
Run Code Online (Sandbox Code Playgroud)
test_file.py:
import somefile
somefile.somefunction()
Run Code Online (Sandbox Code Playgroud)
导致 somefile
请注意,在包或模块中使用时,请__name__
获取文件的名称.没有给出实际模块或包路径的路径,但是它有自己的DunderAlias __file__
,允许这样做.
您应该看到,__name__
主要文件(或程序)将始终返回的位置__main__
,如果它是模块/包,或者其他任何Python脚本运行的东西,将返回其中的文件名称起源于.
实践:
作为一个变量意味着它的值可以被覆盖("可以"并不意味着"应该"),覆盖该值__name__
将导致缺乏可读性.所以不要出于任何原因这样做.如果需要变量定义一个新变量.
它总是假定的价值__name__
是__main__
或文件的名称.再次更改此默认值将导致更多的混淆,它会做得很好,导致进一步的问题.
例:
>>> __name__ = 'Horrify' # Change default from __main__
>>> if __name__ == 'Horrify': print(__name__)
...
>>> else: print('Not Horrify')
...
Horrify
>>>
Run Code Online (Sandbox Code Playgroud)
一般认为包括if __name__ == '__main__'
脚本中的好习惯.
现在回答
if __name__ == '__main__'
:
现在我们知道__name__
事情的行为变得更加清晰:
An if
是一个流控制语句,如果给定的值为true,则包含将执行的代码块.我们已经看到__name__
可以采用它
__main__
或从中导入的文件名.
这意味着如果__name__
等于__main__
那么文件必须是主文件并且必须实际运行(或者它是解释器),而不是导入到脚本中的模块或包.
如果确实__name__
取得了__main__
那个代码块中的任何内容将执行的值.
这告诉我们,如果运行的文件是主文件(或者您直接从解释器运行),那么必须执行该条件.如果它是一个包,那么它不应该,并且值不会__main__
.
模块:
__name__
也可以在模块中用于定义模块的名称
变种:
也可以做其他不常见但有用的东西__name__
,有些我会在这里展示:
仅在文件是模块或包时执行:
if __name__ != '__main__':
# Do some useful things
Run Code Online (Sandbox Code Playgroud)
如果文件是主文件,则运行一个条件,如果不是,则运行另一个条件:
if __name__ == '__main__':
# Execute something
else:
# Do some useful things
Run Code Online (Sandbox Code Playgroud)
您还可以使用它在包和模块上提供可运行的帮助功能/实用程序,而无需精心使用库.
它还允许模块作为主脚本从命令行运行,这也非常有用.
tri*_*eee 25
如果您是初学者,那么您现在需要的唯一答案可能是这个代码对于简单的脚本来说是不必要的。仅当您希望能够使用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))
Run Code Online (Sandbox Code Playgroud)
现在,如果你简单地运行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))
Run Code Online (Sandbox Code Playgroud)
现在,你仍然不能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()
Run Code Online (Sandbox Code Playgroud)
现在,如果您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()
Run Code Online (Sandbox Code Playgroud)
现在,您可以从执行此操作的代码中from fib import fibn
调用该函数。fibn()
import
(我调用该函数fibn()
只是为了更清楚地说明本例中的内容。在现实生活中,您可能会调用它fib()
并执行from fib import fib
。)
注意更加模块化和可重用的设计;该fibn
函数包含实际计算,但没有用户界面部分;并且讨厌的交互式 I/O 被分离到函数中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()
Run Code Online (Sandbox Code Playgroud)
这改变了变量的范围lock
;如果周围的代码需要访问它,您将需要制作它global
(或者,也许更好的是,重构main
为return lock
,并让调用者捕获其自己的局部变量中的值)。
(与 C 等语言不同,该名称main
对 Python 没有特定含义;但使用它作为将要运行的事物的名称是一种常见约定。与main()
C 不同,您仍然需要实际显式调用它,例如 。 )
Inc*_*nnu 23
我认为最好用深入简单的方式打破答案:
__name__
:Python中的每个模块都有一个名为的特殊属性__name__
.它是一个内置变量,它返回模块的名称.
__main__
:像其他编程语言一样,Python也有一个执行入口点,即main.'__main__'
是顶级代码执行的范围的名称.基本上,您有两种使用Python模块的方法:直接将其作为脚本运行,或者导入它.当模块作为脚本运行时,其__name__
设置为__main__
.
因此,当模块作为主程序运行时,__name__
属性的值被设置为__main__
.否则,将值__name__
设置为包含模块的名称.
Pro*_*ica 21
从命令行调用Python文件时,这是一个特殊的功能.这通常用于调用"main()"函数或执行其他适当的启动代码,例如命令行参数处理.
它可以用几种方式编写.另一个是:
def some_function_for_instance_main():
dosomething()
__name__ == '__main__' and some_function_for_instance_main()
Run Code Online (Sandbox Code Playgroud)
我并不是说你应该在生产代码中使用它,但它可以说明没有任何"神奇"的东西if __name__ == '__main__'
.在Python文件中调用main函数是一个很好的约定.
cod*_*ard 20
系统(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))
Run Code Online (Sandbox Code Playgroud)
意味着代码块:
lock = thread.allocate_lock()
thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))
Run Code Online (Sandbox Code Playgroud)
只有在直接运行模块时才会执行; 如果另一个模块正在调用/导入它,则代码块将不会执行,因为__name__的值在该特定实例中不等于" main ".
希望这会有所帮助.
The*_*ron 17
if __name__ == "__main__":
基本上是顶级脚本环境,它指定了解释器('我首先执行的优先级最高').
'__main__'
是顶级代码执行的范围的名称.模块的__name__
设置等于'__main__'
从标准输入,脚本或交互式提示中读取的内容.
if __name__ == "__main__":
# Execute only if run as a script
main()
Run Code Online (Sandbox Code Playgroud)
jac*_*ack 15
在本页的答案中,我一直在阅读这么多内容.我会说,如果你知道这件事,肯定会理解那些答案,否则,你仍然感到困惑.
简而言之,您需要了解以下几点:
import a
动作实际运行所有可以在"a"中运行
由于第1点,您可能不希望在导入时在"a"中运行所有内容
要解决第2点中的问题,python允许您进行条件检查
__name__
是所有.py模块中的隐式变量; 导入a.py时__name__
,a.py模块的值设置为文件名"a"; 当a.py直接使用"python a.py"运行时,这意味着a.py是入口点,那么__name__
a.py模块的值设置为字符串__main__
基于python如何__name__
为每个模块设置变量的机制,你知道如何实现第3点吗?答案很简单,对吧?放一个if条件:if __name__ == "__main__": ...
; 你可以__name__ == "a"
根据你的功能需要放置
python特别重要的是第4点!其余的只是基本逻辑.
Jan*_*amu 14
考虑:
print __name__
Run Code Online (Sandbox Code Playgroud)
上面的输出是__main__
.
if __name__ == "__main__":
print "direct method"
Run Code Online (Sandbox Code Playgroud)
以上陈述是正确的,并打印"直接方法".假设他们在另一个类中导入了这个类,它不会打印"直接方法",因为在导入时它会设置__name__ equal to "first model name"
.
per*_*oud 14
的原因
if __name__ == "__main__":
main()
Run Code Online (Sandbox Code Playgroud)
主要是为了避免因直接导入代码而导致的导入锁定问题.如果您的文件被直接调用(这种情况),您希望运行,但如果您的代码已导入,则导入器必须从真正的主模块输入您的代码以避免导入锁定问题.main()
__name__ == "__main__"
副作用是您自动登录支持多个入口点的方法.您可以使用您的程序main()
作为入口点,但您不必这样做.虽然setup.py
预计main()
,其他工具使用备用入口点.例如,要将文件作为gunicorn
进程运行,请定义app()
函数而不是a main()
.就像使用setup.py
,gunicorn
导入您的代码,因此您不希望它在导入时执行任何操作(因为导入锁定问题).
sam*_*sam 12
您可以将该文件用作脚本以及可导入模块.
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]))
Run Code Online (Sandbox Code Playgroud)
参考:https://docs.python.org/3.5/tutorial/modules.html
Ray*_*ger 10
这个问题的其他答案太长了。实际的机制非常简单,只有两个基本事实:
纯 Python 模块始终在创建时将变量__name__
设置为 string "__main__"
。
__name__
导入模块具有将变量更改为不带扩展名的基本文件名的副作用.py
。
人们编写代码__name__ == '__main__'
是为了测试模块是否已被导入。
导入发生时,某些代码不应运行是很常见的:测试代码、一次性使用代码、命令行前端或 Web 服务器前端。
这个想法是,直接运行模块的人希望这些操作发生,但导入模块的人只想直接访问函数、类和变量。
从其他答案中可以看出,人们似乎能够无休无止地谈论这个话题,但它确实是一件简单的事情,很容易掌握。Python 教程大约需要两分钟的时间来介绍这一点。不要让其他答案淹没你的过度解释:-)
我们__name__ == '__main__':
经常看到。
它检查是否正在导入模块。
换句话说,if
块内的代码只有在代码直接运行时才会被执行。这里的directly
意思是not imported
。
让我们看看它使用打印模块名称的简单代码做了什么:
# test.py
def test():
print('test module name=%s' %(__name__))
if __name__ == '__main__':
print('call test()')
test()
Run Code Online (Sandbox Code Playgroud)
如果我们直接通过 运行代码python test.py
,模块名称为__main__
:
call test()
test module name=__main__
Run Code Online (Sandbox Code Playgroud)
这个答案适用于学习Python的Java程序员.每个Java文件通常都包含一个公共类.您可以通过两种方式使用该类:
从其他文件调用该类.你只需要在调用程序中导入它.
出于测试目的,单独运行类.
对于后一种情况,该类应包含一个public static void main()方法.在Python中,此目的由全局定义的标签提供'__main__'
.
Python 中的每个模块都有一个称为 的特殊属性__name__
。该属性的值__name__
设置为'__main__'
模块作为主程序执行时(例如, running python foo.py
)。
否则, 的值__name__
将设置为调用它的模块的名称。
简单来说:
您在下面看到的代码 if __name__ == "__main__":
只会在您的 python 文件作为“python example1.py”执行时被调用。
但是,如果您希望将 python 文件“example1.py”作为模块导入到另一个 python 文件“example2.py”中,则下面的代码if __name__ == "__main__":
将不会运行或生效。
小智 7
所有的答案几乎都解释了功能。但我将提供一个它的用法示例,这可能有助于进一步澄清这个概念。
假设您有两个 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 是运行的主文件),那么只有代码被执行。
python中的每个模块都有一个称为name的属性。当模块直接运行时,name 属性的值为' main '。否则,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()
Run Code Online (Sandbox Code Playgroud)
我们可以直接执行为
python test.py
Run Code Online (Sandbox Code Playgroud)
输出量
Value of __name__ is: __main__
Going to call hello_world
I am inside hello_world
Run Code Online (Sandbox Code Playgroud)
现在假设我们从其他脚本中调用上述脚本
#script external_calling.py
import test
print(test.apple)
test.hello_world()
print(test.__name__)
Run Code Online (Sandbox Code Playgroud)
当您执行此
python external_calling.py
Run Code Online (Sandbox Code Playgroud)
输出量
42
I am inside hello_world
test
Run Code Online (Sandbox Code Playgroud)
因此,上面的解释是,当您从其他脚本调用test时,如果test.py中的循环名不会执行。
小智 6
您可以通过以下简单示例检查特殊变量__name__
:
创建文件1.py
if __name__ == "__main__":
print("file1 is being run directly")
else:
print("file1 is being imported")
Run Code Online (Sandbox Code Playgroud)
创建*文件2。py
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")
Run Code Online (Sandbox Code Playgroud)
执行文件2.py
输出:
if __name__ == "__main__":
print("file1 is being run directly")
else:
print("file1 is being imported")
Run Code Online (Sandbox Code Playgroud)
当执行 Python 文件时,它会创建许多特殊变量,例如__name__
. 该变量__name__
保存文件的名称。你的问题的答案是
if __name__ == "__main__":
# Do something
Run Code Online (Sandbox Code Playgroud)
这意味着如果正在执行的文件的名称作为源文件而不是模块运行,那么它将运行其中的代码。这可以用一个简单的例子来证明。创建两个 Python 文件,foo.py
以及second.py
. 然后在 中foo.py
输入:
if __name__ == "__main__":
print("file is not imported")
else:
print("file is imported")
Run Code Online (Sandbox Code Playgroud)
在 中second.py
,输入:
import foo
if foo.__name__ == "__main__":
print("file is not imported")
else:
print("file is imported")
Run Code Online (Sandbox Code Playgroud)
除此之外,如果您执行此操作,print(__name__)
则会打印__main__
. 为什么?
因为该文件作为主要源运行,如果您这样做,print(foo.__name__)
它将打印foo因为变量的默认值__name__
是文件的名称,默认情况下我的意思是您也可以更改它。为此,只需转到该foo.py
文件并执行以下操作:__name__ = "name"
。然后,当您运行该文件时,例如,
__name__ = "Hello, World!"
print(__name__)
Run Code Online (Sandbox Code Playgroud)
那么输出将是:
Hello, World!
Run Code Online (Sandbox Code Playgroud)
创建一个文件a.py:
print(__name__) # It will print out __main__
Run Code Online (Sandbox Code Playgroud)
__name__
总是等于__main__
当该文件直接运行时,表明这是主文件。
在同一目录中创建另一个文件b.py:
import a # Prints a
Run Code Online (Sandbox Code Playgroud)
运行。它将打印一个,即导入的文件的名称。
所以,要显示同一个文件的两种不同行为,这是一个常用的技巧:
# Code to be run when imported into another python file
if __name__ == '__main__':
# Code to be run only when run directly
Run Code Online (Sandbox Code Playgroud)
如果此.py文件由其他.py文件导入,则不会执行"if语句"下的代码.
如果此.py由python this_py.py
shell下运行,或在Windows中双击."if语句"下的代码将被执行.
它通常是为测试而编写的.
小智 5
如果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()
Run Code Online (Sandbox Code Playgroud)
运行此脚本打印件时,您可以看到我
一种
如果您导入此文件,请说A到文件B并执行文件B,那么if __name__ == "__main__"
在文件A中将变为false,因此它会打印 您看不到我
b
Python main 函数是任何程序的起点。当程序运行时,Python解释器按顺序运行代码。main 函数仅在作为 Python 程序运行时才会执行...
def main():
print("I am in the function")
print("I am out of the function")
Run Code Online (Sandbox Code Playgroud)
当您运行脚本时显示:
def main():
print("I am in the function")
print("I am out of the function")
Run Code Online (Sandbox Code Playgroud)
而不是代码“我在函数中”。
这是因为我们没有声明调用函数“if__name__==” main ”。
如果您使用它:
def main():
print("I am in the function")
if __name__ == "__main__":
main()
print("I am out of the function")
Run Code Online (Sandbox Code Playgroud)
输出等于
I am out of the function
Run Code Online (Sandbox Code Playgroud)
在 Python 中,if__name__== "__main__"
允许您将 Python 文件作为可重用模块或独立程序运行。
当Python解释器读取源文件时,它将执行其中找到的所有代码。当Python作为主程序运行“源文件”时,它会将特殊变量设置__name__
为具有值"__main__"
。
当您执行 main 函数时,它将读取if
检查是否__name__
等于的语句__main__
。
归档时间: |
|
查看次数: |
2609767 次 |
最近记录: |