编程语言
首页 > 编程语言> > python – 如果__name__ ==“__ main__”怎么办?

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