【问题标题】:Python circular import in custom package and __init__.py自定义包和 __init__.py 中的 Python 循环导入
【发布时间】:2021-03-18 15:40:43
【问题描述】:

我在尝试运行测试时收到 ImportError: cannot import name 'Result' from partial initialized module 'libs.elastic_search_hunt'(很可能是由于循环导入)错误。 但我的代码中没有看到任何循环导入。

我有一个名为 elastic_search_hunt 的包,其中包含 3 个模块:

  1. elastic_query.py
  2. elastic_query_result.py
  3. search_processor.py

我也有 __init__.py 文件,其中包含以下文本:

from libs.elastic_search_hunt.elastic_query import Query
from libs.elastic_search_hunt.search_processor import SearchProcessor
from libs.elastic_search_hunt.elastic_query_result import Result

__all__ = ['Query', 'SearchProcessor', 'Result']  # I guess it does not have any effect

elastic_query.py 只有外部导入。

elastic_query_result.py 一样。

search_processor.py 有那些导入:

from . import Query
from . import Result

然后我有一个测试文件,它导入 Query 类:

from libs.elastic_search_hunt import Query

当我运行测试时,我得到这个错误:

test_query.py:2: in <module>
    from libs.elastic_search_hunt import Query
..\src\libs\elastic_search_hunt\__init__.py:2: in <module>
    from libs.elastic_search_hunt.search_processor import SearchProcessor
..\src\libs\elastic_search_hunt\search_processor.py:4: in <module>
    from . import Result
E   ImportError: cannot import name 'Result' from partially initialized module 'libs.elastic_search_hunt' (most likely due to a circular import)

但我的代码中哪里有循环导入? 我只能假设,当我从测试中导入 Query 时,它也会从 __init__.py 模块中导入 search_processor,而该模块又会加载 再查询一次。但是错误是关于 elastic_query_result 模块中的 Result 的,我只看到 Result 的一个导入。

当我从 __init__.py 中删除 search_processor 时,一切正常。

我已经阅读了很多关于循环导入的问题,但所有这些问题都很明显,并且没有触及 __init__.py。我错过了什么?

【问题讨论】:

  • 你能解释一下 from * * libs.elastic_search_hunt * * import * * Query * * 的作用吗?我还没有找到关于这种双星号使用的任何文档。
  • @SamuelO.D.对不起,那是一个错字。我已经修好了

标签: python import package circular-dependency


【解决方案1】:

TL;DR:将from . import Query 替换为from .elastic_query import Query

说明:

当您从 libs.elastic_search_hunt 模块导入某些内容时,它首先会加载 __init__.py。由于每个模块首先执行 import __init__.py 也正在执行。

然后 Python 从__init__.py 和第二行执行代码

from libs.elastic_search_hunt.search_processor import SearchProcessor

它导入search_processor.py。由于它是第一次导入 - 必须执行文件 - 因此您在该文件中的所有导入也必须立即执行:

正如您提到的,您的文件中有以下导入:

from . import Query
from . import Result

此时你告诉python加载libs.elastic_search_hunt整个模块并从中获取Query, Result。 Python 也是。

它会尝试加载libs/elastic_search_hunt/__init__.py,但是等等……它仍然没有完全加载。所以它必须加载它,但为了正确加载它必须首先加载search_processor,这需要加载elastic_search_hunt/__init__.py....哦,有一个循环。

因此,为了避免这种行为,您应该明确说明您希望从哪个模块加载 QueryResult,因此更改

from . import Query
from . import Result

from .elastic_query import Query
from .elastic_query_result import Result

示例:失败 示例:成功

【讨论】:

    猜你喜欢
    • 2013-04-21
    • 1970-01-01
    • 1970-01-01
    • 2012-02-24
    • 1970-01-01
    • 2017-07-25
    • 1970-01-01
    • 1970-01-01
    • 2010-10-09
    相关资源
    最近更新 更多