个性化阅读
专注于IT技术分析

如何理解Python中if__name__==“__main__”?它是什么意思,有什么用?

如何理解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中运行脚本只是设置一些魔术变量并导入脚本是很优雅的。 “运行”脚本是导入脚本模块的副作用。

赞(0) 打赏
未经允许不得转载:srcmini » 如何理解Python中if__name__==“__main__”?它是什么意思,有什么用?
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!

 

觉得文章有用就打赏一下文章作者

微信扫一扫打赏