# 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__
它执行文件中找到的所有代码。
让我们看看它是如何工作的,以及它与你有关__name__我们在Python脚本中经常看到的检查问题的关系。
让我们使用稍微不同的代码示例来探索导入和脚本的工作方式。假设以下文件位于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交互程序读取源文件时,它首先定义了一些特殊变量。在这种情况下,我们关心__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"
设置特殊变量后,解释器一次执行一个语句,执行模块中的所有代码。你可能想要在代码示例侧面打开另一个窗口,以便你可以按照以下说明进行操作。
总是
# Find and load a module given its string name, "math", # then assign it to a local variable called math. math = __import__("math")
仅当你的模块是主程序时
仅当你的模块由另一个导入时
总之
摘要
总而言之,这是两种情况下的打印内容:
# 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在命令行上说会怎样?为什么?
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")
# 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")