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 解释器读取一个源文件时,它做两件事。
__name__
,然后__name__
检查的问题有什么关系。
代码样本让我们使用一个稍微不同的代码样本来探索导入和脚本的工作原理。 假设下面的内容是在一个叫做 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")
当 Python interpeter 读取一个源文件时,它首先定义了一些特殊变量。在本例中,我们关心的是 __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
在这种情况下,解释器将查看你的模块的文件名,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"
设置好特殊变量后,解释器将执行模块中的所有代码,一次一个语句。你可能想在有代码样本的一侧打开另一个窗口,以便你能跟着这个解释走。
总是
1.它打印出字符串"before import"
(不带引号)。
2.2.它加载math
模块并将其分配给一个叫做math
的变量。这相当于用下面的语句代替 import math
(注意 __import__
是 Python 中的一个低级函数,它接收一个字符串并触发实际的导入)。
# 找到并加载一个模块,给出它的字符串名称,"math"。
# 然后把它赋值给一个叫做 math 的局部变量。
math = __import__("math")
3.它打印出字符串"before functionA"
。
4.它执行def
块,创建一个函数对象,然后将该函数对象分配给一个叫做functionA
的变量。
5.它打印出字符串"before functionB"
。
6.它执行第二个def
块,创建另一个函数对象,然后将其分配给一个叫做functionB
的变量。
7.7. 它打印出字符串 "before __name__ guard"
。
只有当你的模块是主程序的时候。
8.如果你的模块是主程序,那么它将看到__name__
确实被设置为"__main__"
并调用两个函数,打印字符串"函数A"
和"函数B 10.0"
。
只有当你的模块被其他模块导入时。
8.(instead) 如果你的模块不是主程序,而是被另一个模块导入,那么__name__
将是"foo"
,而不是"__main__"
,并且它将跳过if
语句的主体。
总是
9.在这两种情况下,它都会打印字符串"在__name__守护之后"
。
总结
综上所述,在这两种情况下会打印的内容如下。
# 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
# What gets printed if foo is imported as a regular module
before import
before functionA
before functionB
before __name__ guard
after __name__ guard
你可能会自然而然地想,为什么有人会想要这样做。 好吧,有时候你想写一个.py
文件,既可以被其他程序和/或模块作为模块使用,又可以作为主程序本身运行。 例子。
你的模块是一个库,但你想有一个脚本模式,它可以运行一些单元测试或一个演示。
你的模块只作为一个主程序使用,但它有一些单元测试,测试框架通过导入像你的脚本一样的.py
文件并运行特殊的测试函数来工作。你不希望它只是因为导入了模块而尝试运行脚本。
问题。我可以有多个__name__
检查块吗? 回答:这样做很奇怪,但语言不会阻止你。
假设以下内容是在foo2.py
中。 如果你在命令行中说python foo2.py
会发生什么?为什么?
<! -- language: python -->
# 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")
foo3.py
中的__name__
检查,会发生什么。# 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")
# Suppose this is in foo4.py
__name__ = "__main__"
def bar():
print("bar")
print("before __name__ guard")
if __name__ == "__main__":
bar()
print("after __name__ guard")
当你的脚本作为一个命令传递给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__"
。
if __name__ == "__main__"
是当使用python myscript.py
这样的命令从(比如)命令行运行脚本时,运行的部分。