Python 自定义包中的循环导入和 __init__.py
Python circular import in custom package and __init__.py
我收到 ImportError: cannot import name 'Result' from partially initialized module 'libs.elastic_search_hunt' (most likely due to a circular import) 当我尝试运行 测试。
但是我在我的代码中没有看到任何循环导入。
我有一个名为 elastic_search_hunt 的包,其中包含 3 个模块:
- elastic_query.py
- elastic_query_result.py
- 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 class:
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 时,它也会从 [=83 中导入 search_processor =] 模块依次加载 Query 一次。但是错误是关于 elastic_query_result 模块中的 Result 我只看到 Result[=59= 的一个导入].
当我从 __init__.py 中删除 search_processor 时,一切正常。
我看过很多关于循环导入的issues,但是都比较明显,没有触及__init__.py。我错过了什么?
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
....哦,好吧,有一个循环。
因此,为了避免这种行为,您应该明确说明您希望从哪个模块加载 Query
和 Result
,因此更改
from . import Query
from . import Result
至
from .elastic_query import Query
from .elastic_query_result import Result
示例:失败
示例:成功
我收到 ImportError: cannot import name 'Result' from partially initialized module 'libs.elastic_search_hunt' (most likely due to a circular import) 当我尝试运行 测试。 但是我在我的代码中没有看到任何循环导入。
我有一个名为 elastic_search_hunt 的包,其中包含 3 个模块:
- elastic_query.py
- elastic_query_result.py
- 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 class:
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 时,它也会从 [=83 中导入 search_processor =] 模块依次加载 Query 一次。但是错误是关于 elastic_query_result 模块中的 Result 我只看到 Result[=59= 的一个导入].
当我从 __init__.py 中删除 search_processor 时,一切正常。
我看过很多关于循环导入的issues,但是都比较明显,没有触及__init__.py。我错过了什么?
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
....哦,好吧,有一个循环。
因此,为了避免这种行为,您应该明确说明您希望从哪个模块加载 Query
和 Result
,因此更改
from . import Query
from . import Result
至
from .elastic_query import Query
from .elastic_query_result import Result
示例:失败