循环进口地狱

V.K*_*.K. 13 python import circular-dependency

Python是非常优雅的语言.好吧,除了......除了进口.我仍然无法以对我来说似乎很自然的方式工作.

我有一个MyObjectA存档的类mypackage/myobjecta.py.该对象使用了一些实用程序函数mypackage/utils.py.所以在我myobjecta.py写的第一行:

from mypackage.utils import util_func1, util_func2
Run Code Online (Sandbox Code Playgroud)

但是一些实用程序函数创建并返回新的实例MyObjectA.所以我需要写utils.py:

from mypackage.myobjecta import MyObjectA
Run Code Online (Sandbox Code Playgroud)

好吧,不,我不能.这是一个循环导入,Python将拒绝这样做.

关于这个问题,这里有很多问题,但似乎都没有给出令人满意的答案.从我在所有答案中可以阅读的内容:

  1. 重新组织你的模块,你做错了!但即使在我提出的这么简单的情况下,我也不知道如何更好地组织我的模块.
  2. 尝试import ...而不是from ... import ... (我个人不喜欢编写并可能重构所有全名限定符;我喜欢看看我从外部世界导入到模块中的确切内容).那会有帮助吗?我不确定,还有循环进口.
  3. 在你使用其他模块的东西之前,做一些黑客就像在函数体的内部范围中导入一些东西.

我仍然希望有解决方案4)这将是Pythonic在功能和优雅,简单和工作的意义上.或者没有?

注意:我主要是一个C++程序员,上面的例子通过包含相应的标题很容易解决,我不相信它在Python中是不可能的.

Seb*_*zny 2

在函数体中导入某些东西并没有什么黑客之处,它是一个绝对有效的模式:

def some_function():
    import logging
    do_some_logging()
Run Code Online (Sandbox Code Playgroud)

通常ImportErrors 仅因方式而引发import()调用时评估整个文件的顶级语句的方式而引发 s 。

如果你没有逻辑循环依赖... ,在 python 中没有什么是不可能的...

如果您确实希望导入的内容位于顶部,则有一种解决方法

来自 David Beazley 的精彩演讲《模块和包:生与死!》- PyCon 20151:54:00这是一种处理 python 中循环导入的方法:

try:
    from images.serializers import SimplifiedImageSerializer
except ImportError:
    import sys
    SimplifiedImageSerializer = sys.modules[__package__ + '.SimplifiedImageSerializer']
Run Code Online (Sandbox Code Playgroud)

它尝试导入SimplifiedImageSerializer,如果ImportError引发(由于循环导入错误或它不存在),它将从导入缓存中提取它。

PS:您必须以 David Beazley 的声音阅读整篇文章。

  • 如果相关模块已经导入,则永远不会引发“ImportError”。当导入某些东西时,Python 会检查它是否已经导入,如果是的话,简单地创建一个指向它的指针。仅当“SimplifiedImageSerializer”因不存在而无法导入或创建循环导入时,才会执行“ except ”语句。 (2认同)