模块可以周期性地相互导入,但有一个问题。在简单的情况下,它应该通过将 import 语句移动到文件底部或不使用 from 语法来工作。
这就是为什么有效:
当你导入一个模块时,Python 首先检查sys.modules。如果它在那里,它只是从那里进口。如果它不存在,它会尝试以正常方式导入它;基本上,它会找到文件并运行其中的内容。
运行模块会填充模块的内容。例如,假设我们有这个模块,创造性地命名为example_opener:
import webbrowser
def open_example():
webbrowser.open('http://www.example.com/')
一开始,模块是空的。然后 Python 执行:
import webbrowser
之后,模块只包含webbrowser。然后 Python 执行:
def open_example():
webbrowser.open('http://www.example.com/')
Python 创建open_example。现在该模块包含webbrowser 和open_example。
说webbrowser 包含此代码:
from example_opener import open_example
def open(url):
print url
说example_opener首先被导入。执行此代码:
import webbrowser
webbrowser还没有被导入,所以Python执行webbrowser的内容:
from example_opener import open_example
example_opener已被导入,但尚未完全执行。 Python 不在乎。 Python 将模块从sys.modules 中拉出。此时,example_opener 仍为空。它还没有定义open_example,甚至还没有完成导入webbrowser。 Python在example_opener中找不到open_example,所以失败了。
如果我们从webbrowser 的末尾导入open_example 并从example_opener 的末尾导入webbrowser 会怎样? Python 将从执行以下代码开始:
def open_example():
webbrowser.open('http://www.example.com/')
webbrowser 尚不存在,但在调用 open_example 之前无关紧要。现在example_opener 只包含open_example。然后执行:
import webbrowser
它还没有被导入,所以 Python 执行webbrowser。它开始了:
def open(url):
print url
它定义了open。然后执行:
from example_opener import open_example
example_opener 在sys.modules 中,所以它使用它。 example_opener 包含open_example,所以它成功了。 Python 完成导入webbrowser。从example_opener 导入webbrowser 到此结束。这是example_opener 中的最后一件事,所以example_opener 的导入也完成了,也成功了。