72

我有一个带有以下行的 Bottle 网络服务器模块:

from foobar.formtools import auto_process_form_insert

foobar.formtools模块包含这一行:

from foobar.webserver import redirect, redirect_back

当然,两者都会导致以下错误(分别):

ImportError:无法导入名称 auto_process_form_insert
ImportError:无法导入名称重定向

在 Python 中两个模块不能相互导入并且所有模块导入本质上必须是分层的,这仅仅是一个事实,还是我做错了什么?或者,是否有没有将所有这些不错的功能放在新模块中的解决方法?

4

2 回答 2

93

模块可以周期性地相互导入,但有一个问题。在简单的情况下,它应该通过将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. 现在模块包含webbrowseropen_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,甚至还没有完成导入webbrowseropen_examplePython在中找不到example_opener,所以它失败了。

如果我们open_example从 endwebbrowserwebbrowserend导入example_opener怎么办?Python 将从执行以下代码开始:

def open_example():
    webbrowser.open('http://www.example.com/')

webbrowseropen_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. 从. webbrowser_ example_opener这是 中的最后一件事example_opener,所以example_opener完成的导入也成功了。

于 2012-07-28T05:25:48.937 回答
35

不要做from ... import ...。只需import ...使用模块名称执行并引用其对象即可。

于 2012-07-28T05:37:47.800 回答