两个Python模块相互需要';s的内容-可以吗?
我有一个瓶子Web服务器模块,其行如下:两个Python模块相互需要';s的内容-可以吗?,python,python-module,Python,Python Module,我有一个瓶子Web服务器模块,其行如下: from foobar.formtools import auto_process_form_insert 而foobar.formtools模块包含以下行: from foobar.webserver import redirect, redirect_back 当然,两者都会导致以下错误(分别): 导入错误:无法导入名称自动处理表单插入 ImportError:无法导入名称重定向 这仅仅是一个事实,在Python中,两个模块不能相互导入,所有模块
from foobar.formtools import auto_process_form_insert
而foobar.formtools
模块包含以下行:
from foobar.webserver import redirect, redirect_back
当然,两者都会导致以下错误(分别):
导入错误:无法导入名称自动处理表单插入ImportError:无法导入名称重定向 这仅仅是一个事实,在Python中,两个模块不能相互导入,所有模块导入本质上都必须是分层的,还是我做错了什么?或者,除了将所有这些漂亮的功能放在新模块中之外,还有其他解决方法吗?模块可以周期性地相互导入,但有一个缺点。在简单的情况下,它应该通过将
import
语句移动到文件底部或不使用from
语法来工作
这就是为什么这样做的原因:
导入模块时,Python首先检查sys.modules
。如果它在那里,它只是从那里进口。如果它不在那里,它会尝试以正常的方式导入它;基本上,它会找到文件并运行其中的内容
运行模块会填充模块的内容。例如,假设我们有这个模块,创造性地命名为example\u opener
:
import webbrowser
def open_example():
webbrowser.open('http://www.example.com/')
from example_opener import open_example
开始时,模块为空。然后Python执行:
import webbrowser
import webbrowser
from example_opener import open_example
之后,模块仅包含webbrowser
。然后Python执行以下操作:
def open_example():
webbrowser.open('http://www.example.com/')
Python创建open\u示例
。现在,模块包含webbrowser
和open\u示例
说webbrowser
包含此代码:
from example_opener import open_example
def open(url):
print url
def open_example():
webbrowser.open('http://www.example.com/')
假设先导入示例\u opener
。执行此代码:
import webbrowser
webbrowser
尚未导入,因此Python执行webbrowser
的内容:
import webbrowser
def open_example():
webbrowser.open('http://www.example.com/')
from example_opener import open_example
示例\u opener
已导入,但尚未完全执行。Python不在乎。Python将模块从sys.modules
中拉出。此时,example\u opener
仍然为空。它还没有定义open\u示例
,甚至还没有完成导入webbrowser
。Python在example\u opener
中找不到open\u example
,因此失败
如果我们从webbrowser
的末尾导入open\u示例
,从example\u opener
的末尾导入webbrowser
,会怎么样?Python将首先执行以下代码:
from example_opener import open_example
def open(url):
print url
def open_example():
webbrowser.open('http://www.example.com/')
webbrowser
尚不存在,但在调用open\u示例之前,它并不重要。现在example\u opener
只包含open\u example
。然后执行:
import webbrowser
import webbrowser
from example_opener import open_example
它还没有被导入,所以Python执行webbrowser
。它开始于:
def open(url):
print url
它定义了打开
。然后执行:
import webbrowser
import webbrowser
from example_opener import open_example
example\u opener
位于sys.modules
中,因此它使用了它example\u opener
包含open\u example
,因此它成功了。Python完成导入webbrowser
。这就结束了从example\u opener
导入webbrowser
。这是example\u opener
中的最后一件事,因此导入example\u opener
也会成功完成。不要从中执行。。。导入…
。只需导入…
并使用模块名引用其对象。。这通常是我在django要做的事情,有时候你只需要循环导入。在底部或函数或方法范围内导入。@Codemonkey:我注意到您添加了可以避免使用来自的。。。导入…
语法,但我在顶部的回答中已经提到了这一点:“在简单的情况下,它应该通过[…]不使用from
语法来工作。”不过我认为这不会解决循环导入问题。@jdi:会的。在导入时,模块将是空的,但由于它没有尝试获取模块内部的任何内容(但),这并不重要。我想说,不特别建议将导入放在bottom或混合点。作为一般的经验法则。这也使得可维护性更容易,想象有人在底部看到导入,认为在那里很愚蠢,将它们移动到顶部,然后看着代码中断。如果您尝试在导入的第一个模块的模块范围内访问第二个模块的属性,则可能会出现相同的错误。例如,假设我从内部bar.py
导入foo。我从内部foo.py
导入条形图。假设foo.py
首先得到处理foo->import bar->import foo
,其中最终的import foo
将引用部分实例化的foo
模块。现在,如果在bar.py内部,在模块范围内,我做了类似于bar_常量=max(100,foo.foo_常量)
的操作,它将失败,因为bar.py可以获得句柄的foo
尚未实例化foo_常量。
。正如我在回答中所解释的,模块可以相互导入,但如果需要这样做,您可能需要重新考虑您的设计。我认为这个解释更容易理解:另请参阅