You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决因__init__.py导入导致的循环ImportError问题?

解决Python单元测试中的循环导入问题

问题背景

开发Python 3项目时使用unittest编写单元测试,遇到循环导入导致的ImportError:被测文件periphery/foo.py从core包导入内容,而core/__init__.py又从periphery/foo.py导入Foo。需要保留core/__init__.py中的导入语句,找到不删除该导入前提下让测试正常运行的方案。

复现示例的项目结构

├───core
│       bar.py
│       __init__.py
│
├───periphery
│       foo.py
│       __init__.py
│
└───tests
    │   __init__.py
    │
    ├───core
    │       __init__.py
    │
    └───periphery
            test_foo.py
            __init__.py

相关文件代码

core/init.py

# --- periphery ---
from periphery.foo import Foo

periphery/foo.py

from core.bar import Bar

def Foo():
    bar = Bar()
    return bar

tests/periphery/test_foo.py

from unittest import TestCase

from periphery.foo import Foo

class Test(TestCase):

    def test_foo(self):
        """ Test that Foo() returns "bar" """
        self.assertEqual(Foo(), "bar")

运行测试触发的错误

ImportError: cannot import name 'Foo' from partially initialized module 'periphery.foo' (most likely due to a circular import)

可行解决方案

方法1:使用延迟导入(Python 3.7+)

修改core/__init__.py,利用__getattr__实现按需导入,避免模块加载阶段触发循环:

# core/__init__.py
def __getattr__(name):
    if name == "Foo":
        from periphery.foo import Foo
        return Foo
    raise AttributeError(f"module 'core' has no attribute '{name}'")

只有当代码实际访问core.Foo时才会执行导入,从根源上避开初始化时的循环依赖。

方法2:调整测试文件的导入顺序

在测试文件中先导入core.bar,让core模块完成初始化后再导入periphery.foo:

from unittest import TestCase

# 先完成core.bar的导入,确保core模块初始化完成
from core.bar import Bar
from periphery.foo import Foo

class Test(TestCase):
    def test_foo(self):
        """ Test that Foo() returns "bar" """
        self.assertEqual(Foo(), "bar")

注意:这种方法依赖导入顺序,稳定性较弱,适合临时调试场景。

方法3:代码重构解耦

如果项目允许,抽离共享依赖到独立模块打破循环:

  1. 新增common包,将Bar移至common/bar.py
  2. periphery/foo.py改为从common.bar导入Bar
  3. 若core包需要Bar,也从common.bar导入
    这种方式从结构上消除循环依赖,是最彻底的解决方案。

内容的提问来源于stack exchange,提问作者Christian Singer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 16:05:48