python – 如果__name__ ==“__ main__”怎么办?
作者:互联网
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的文件中.
# 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"
执行模块的代码
设置特殊变量后,解释器将执行模块中的所有代码,一次执行一个语句.您可能希望使用代码示例打开另一个窗口,以便您可以按照此说明进行操作.
总是
>它打印字符串“导入前”(不带引号).
>它加载数学模块并将其分配给一个名为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")
>它打印字符串“在functionA之前”.
>它执行def块,创建一个函数对象,然后将该函数对象分配给一个名为functionA的变量.
>它打印字符串“在functionB之前”.
>它执行第二个def块,创建另一个函数对象,然后将其分配给名为functionB的变量.
>它打印字符串“在__name__ guard之前”.
仅当您的模块是主程序时
>如果您的模块是主程序,那么它将看到__name__确实设置为“__main__”并且它调用两个函数,打印字符串“Function A”和“Function B 10.0”.
仅当您的模块被另一个导入时
>(相反)如果你的模块不是主程序而是由另一个模块导入,则__name__将是“foo”,而不是“__main__”,它将跳过if语句的主体.
总是
>它将在两种情况下打印字符串“在__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中运行脚本只是设置一些魔术变量并导入脚本是很优雅的. “运行”脚本是导入脚本模块的副作用.
思想的食物
>问题:我可以有多个__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")
>现在,弄清楚如果删除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,namespaces,main,idioms,python-module 来源: https://codeday.me/bug/20190910/1802051.html