gpt4 book ai didi

python-3.x - 避免部分初始化的模块 ImportError

转载 作者:行者123 更新时间:2023-12-05 06:52:50 27 4
gpt4 key购买 nike

上下文

假设我有以下模块:

.
└── my_module
├── __init__.py
├── my_module_A.py (defines ClassA)
└── my_module_B.py (defines ClassB, which needs ClassA)

文件如下:

# __init__.py

from .my_module_A import ClassA
from .my_module_B import ClassB
# my_module_A.py

from my_module import ClassB

class ClassA:

def __init__(self, class_b: ClassB):
pass
# my_module_B.py

class ClassB:
def __init__(self):
pass

重要的是 ClassB 需要一个 ClassA 的实例实例化。

问题

导入模块my_module 引发ImportError:

>>> # Working directory is the parent of my_module
>>> import my_module
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "foo/Module/my_module/__init__.py", line 3, in <module>
from .my_module_A import ClassA
File "foo/Module/my_module/my_module_A.py", line 3, in <module>
from my_module import ClassB
ImportError: cannot import name 'ClassB' from partially initialized module 'my_module' (most likely due to a circular import) (foo/Module/my_module/__init__.py)

问题似乎出在下面。当导入 my_module 时,Python 去通过它的 __init__.py 并开始从 my_module_A 导入 ClassA。此文件从 my_module_B 导入自身 ClassB 因此导入了此类对于 my_module 也是如此。在 my_module_A 之后,Python 尝试导入 ClassB来自 my_module ;但是它已经被 my_module_A 导入了,所以 Python引发 ImportError

Python 提示错误可能来自循环导入,但这不是这里的情况。我真的认为问题在于类 ClassB 是导入两次:如果我不在 __init__.py 中导入 my_module_B 并使用my_module_A中的my_module_B相对导入,导入成功并且没有出现异常。

寻找解决方案

一个可能的解决方案是在 python 文件中只使用相对导入我的模块。问题是 my_module 中的一些子模块需要他们自己有很多来自 my_module 的类(其中一些大约有 20 个)并且它对于必须知道精确文件名的维护者来说是丑陋和不便的定义类的地方。所以我的问题是:如何在 my_module 子模块中继续使用 from my_modyle import … 导入?非常感谢。

附言你们中的一些人可能会建议重新考虑我的模块组织。我想到了那但是没有规范的方法可以做到这一点而且这个平面结构确实是更容易,更清晰。因此,如果可能的话,我想避免这种情况。

Python 版本:3.9.1

最佳答案

问题的根源是当 my_module_A 时 ClassB 还没有被加载到 my_module (在 __init__.py 中) 正在导入(错误消息中的“部分初始化”位暗示了这一点)。您需要在 __init__.py 中手动对导入进行排序,以便依赖项出现在使用它们的模块之前:

# __init__.py

from .my_module_B import ClassB
from .my_module_A import ClassA # uses ClassB

一个更可靠的解决方案是跳过 __init__.py 并直接从 my_module_B 导入,但是正如您所说,这对于很多模块来说会变得笨拙。

# my_module_A.py

# relative imports also work here
from my_module.my_module_B import ClassB

class ClassA:
def __init__(self, class_b: ClassB):
pass

关于python-3.x - 避免部分初始化的模块 ImportError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65900435/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com