简体   繁体   English

Python 循环导入自定义 package 和 __init__.py

[英]Python circular import in custom package and __init__.py

I get ImportError: cannot import name 'Result' from partially initialized module 'libs.elastic_search_hunt' (most likely due to a circular import) error when I try to run tests.当我尝试运行测试时,我得到ImportError: cannot import name 'Result' from partial initialized module 'libs.elastic_search_hunt'(很可能是由于循环导入)错误。 But I does not see any circular imports in my code.但是我在我的代码中没有看到任何循环导入。

I have a package, named elastic_search_hunt which contains 3 modules:我有一个名为elastic_search_hunt的 package,它包含 3 个模块:

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

And I also have __init__.py file with following text:而且我还有__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 has only external imports. elastic_query.py只有外部导入。

elastic_query_result.py the same. elastic_query_result.py相同。

search_processor.py has those import: search_processor.py有这些导入:

from . import Query
from . import Result

Then I have a test file, which imports Query class:然后我有一个测试文件,它导入查询class:

from libs.elastic_search_hunt import Query

When I run tests, I get this errors:当我运行测试时,我得到这个错误:

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)

But where is any circular import in my code?但是我的代码中的任何循环导入在哪里? I only can assume that when I import Query from tests, it also import search_processor from the __init__.py module which in turn loads Query one more time.我只能假设当我从测试中导入Query时,它也会从__init__.py模块中导入search_processor ,这又会再次加载Query一次。 But the error is about Result in elastic_query_result module and I see only one import of Result .但错误是关于elastic_query_result模块中的Result ,我只看到一个Result导入。

When i delete search_processor from __init__.py everything works fine.当我从__init__.py中删除 search_processor 时,一切正常。

I have read a lot of issues about circular imports, but all of them was quite obvious and does not touch the __init__.py .我已经阅读了很多关于循环导入的问题,但所有这些问题都很明显,并且没有触及__init__.py What am I missing?我错过了什么?

TL;DR : replace from. import Query TL;DR :替换from. import Query from. import Query with from.elastic_query import Query使用from.elastic_query import Query from. import Query

Explanation:解释:

When you import something from libs.elastic_search_hunt module it loads __init__.py at first.当您从libs.elastic_search_hunt模块导入某些内容时,它首先会加载__init__.py Since every module executes at first import __init__.py also being executed.由于每个模块首先执行 import __init__.py也正在执行。

Then Python executes code from __init__.py and at second line然后 Python 从__init__.py和第二行执行代码

from libs.elastic_search_hunt.search_processor import SearchProcessor

it imports search_processor.py .它导入search_processor.py Since it's first import - file must be executed - therefore all your imports in that file must be executed right now as well:由于它是第一次导入 - 必须执行文件 - 因此您在该文件中的所有导入也必须立即执行:

As you mentioned you have the following imports in your file:正如您提到的,您的文件中有以下导入:

from . import Query
from . import Result

At this point you tell python to load libs.elastic_search_hunt entire module and take Query, Result from it.此时您告诉 python 加载libs.elastic_search_hunt整个模块并从中获取Query, Result So Python does.所以 Python 可以。

It makes an attempt to load libs/elastic_search_hunt/__init__.py but wait... it is still not loaded completely.它尝试加载libs/elastic_search_hunt/__init__.py但等等……它仍然没有完全加载。 So it must load it, but in order to load it properly it must firstly load search_processor which requires elastic_search_hunt/__init__.py to be loaded.... oh well, there's a loop.所以它必须加载它,但为了正确加载它必须首先加载需要加载elastic_search_hunt/__init__.pysearch_processor ......哦,好吧,有一个循环。

So in order to avoid such behaviour you should explicitly say from which module exactly you wish to load Query and Result , therefore change因此,为了避免这种行为,您应该明确说明您希望从哪个模块加载QueryResult ,因此更改

from . import Query
from . import Result

to

from .elastic_query import Query
from .elastic_query_result import Result

Example: Failed示例:失败失败的 Example: Success示例:成功成功

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM