如何理解Python中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__,然后
它执行文件中找到的所有代码。
让我们看看它是如何工作的,以及它与你在Python脚本中总是看到的关于__name__检查的问题的关系。
代码示例
让我们使用稍微不同的代码示例来探索导入和脚本的工作方式。假设以下内容位于名为foo.py的文件中。
#假设这是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__变量,即
#就像解释器在顶部插入它一样
作为主程序运行时模块的#。
__name__ =“__
main__”
当你的模块被另一个导入时
另一方面,假设某些其他模块是主程序,它会导入你的模块。这意味着在主程序或主程序导入的其他模块中有这样的声明:
#假设这是在其他一些主程序中。
导入foo
在这种情况下,解释器将查看模块的文件名foo.py,剥离.py,并将该字符串分配给模块的__name__变量,即
#就像解释器在顶部插入它一样
从其他模块导入模块时的#个。
__name__ =“foo”
执行模块的代码
设置特殊变量后,解释器将执行模块中的所有代码,一次执行一个语句。你可能希望使用代码示例打开另一个窗口,以便你可以按照此说明进行操作。
总是
它打印字符串“导入前”(不带引号)。
它加载数学模块并将其分配给一个名为math的变量。这相当于用以下代码替换import math(注意__import__是Python中的一个低级函数,它接受一个字符串并触发实际导入):
#找到并加载一个给定字符串名称“math”的模块,
#然后将其分配给名为math的局部变量。
math = __import __(“math”)
它打印字符串“在functionA之前”。
它执行def块,创建一个函数对象,然后将该函数对象分配给一个名为functionA的变量。
它打印字符串“在functionB之前”。
它执行第二个def块,创建另一个函数对象,然后将其分配给一个名为functionB的变量。
它打印字符串“在__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
# 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文件(如脚本)和运行特殊测试功能来工作。你不希望它尝试运行脚本只是因为它正在导入模块。
你的模块主要用作主程序,但它也为高级用户提供了一个程序员友好的API。
除了这些例子之外,在Python中运行脚本只是设置一些魔术变量并导入脚本是很优雅的。 “运行”脚本是导入脚本模块的副作用。
来源:
https://www.srcmini02.com/1029.html