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

Setuptools可编辑模式在项目目录外无法正常工作的问题排查

可编辑模式下pip install -e .导入包模块失败问题

项目结构

setuptools_test/
├── pyproject.toml
└── setuptools_test/
    ├── __init__.py
    ├── base.py
    └── module/
        ├── __init__.py
        └── base.py

配置与代码文件

pyproject.toml

[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

[project]
name = "setuptools_test"
version = "0.0.1"
dependencies = [
    "requests",
    'importlib-metadata; python_version>="3.11"',
]

setuptools_test/init.py

from .base import FirstClass

setuptools_test/base.py

class FirstClass: ...

setuptools_test/module/init.py

from .base import SecondClass

setuptools_test/module/base.py

from setuptools_test import FirstClass

class SecondClass(FirstClass): ...

问题现象

在setuptools_test/目录执行python -m pip install -e .完成可编辑模式安装后,在项目目录外启动Python Shell执行from setuptools_test.module import SecondClass时,抛出以下错误:

>>> from setuptools_test.module import SecondClass
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File ".../setuptools_test/setuptools_test/module/__init__.py", line 1, in <module>
    from .base import SecondClass
  File ".../setuptools_test/setuptools_test/module/base.py", line 1, in <module>
    from setuptools_test import FirstClass
ImportError: cannot import name 'FirstClass' from 'setuptools_test' (unknown location)

非可编辑模式(pip install .)下安装则一切正常。

环境信息

  • 系统:Ubuntu 22.04.4
  • Python版本:3.11(apt安装)
  • pip版本:25.2

python -m pip freeze --all输出:

autocommand==2.2.2
backports.tarfile==1.2.0
build==1.3.0
certifi==2025.8.3
charset-normalizer==3.4.3
idna==3.10
importlib_metadata==8.7.0
jaraco.context==6.0.1
jaraco.functools==4.3.0
jaraco.text==4.0.0
more-itertools==10.7.0
packaging==25.0
pip==22.0.2
platformdirs==4.4.0
pyproject_hooks==1.2.0
requests==2.32.5
setuptools==80.9.0
setuptools_test @ file:///.../setuptools_test
urllib3==2.5.0
wheel==0.45.1
zipp==3.23.0

问题原因与解决办法

这是可编辑模式下循环导入触发的初始化顺序冲突:

当module/base.py用绝对导入from setuptools_test import FirstClass时,Python会尝试加载顶层setuptools_test包的__init__.py,但此时module/base.py本身正在被加载,导致顶层包的初始化流程还没完成,FirstClass还没被导入到顶层命名空间,从而抛出导入错误。非可编辑模式下正常是因为安装后包文件被复制到site-packages,Python导入机制会优先加载完整的包,不会出现这种初始化顺序问题。

推荐两种解决方式:

方式1:改用相对导入

修改setuptools_test/module/base.py的导入语句为相对导入,直接从上级模块导入:

from ..base import FirstClass

class SecondClass(FirstClass): ...

方式2:延迟导入(适合必须用绝对导入的场景)

如果业务上必须使用绝对导入,可以延迟导入FirstClass,避免在模块加载阶段触发循环导入:

# 模块级延迟导入
def __getattr__(name):
    if name == "FirstClass":
        from setuptools_test import FirstClass
        return FirstClass
    raise AttributeError(f"module {__name__} has no attribute {name}")

class SecondClass(__getattr__("FirstClass")): ...

或者在类的方法内部导入(比如__init__):

class SecondClass:
    def __init__(self, *args, **kwargs):
        from setuptools_test import FirstClass
        super().__init__(*args, **kwargs)

内容的提问来源于stack exchange,提问作者kouign amann

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 11:27:24