pip install -e.出现xxx module not found error的问题解决方案
目录
- 问题说明与解决方案
- 添加 pyproject.toml
- 问题原因详细解释
- 使用什么标准安装取决于什么
- 1. 关键决定因素
- 2. 具体行为规则
- (1) 当项目有pyproject.toml时
- (2) 当项目无pyproject.toml时
- 3. 版本兼容性对照表
- 4. 如何强制选择安装方式?
- (1) 强制使用传统setup.py(不推荐)
- (2) 强制使用 PEP 517/518
- 5. 为什么你的案例中toml在主环境无效?
- 6. 最佳实践建议
- 总结
问题说明与解决方案
在本地安装wheeled_lab这个包的时候一直出现toml module找不到的错误,但是不管是conda的环境还是python的基本环境都已经安装过了toml包,后来发现是Python包在构建时的构建标准问题。
Python 包安装系统正在从旧的 setup.py 方式过渡到新的 PEP 517/518 标准(使用 pyproject.toml
)。
当在Ubuntu22.04
运行 pip install -e .
时,pip
会尝试使用现代的 PEP 517 标准来构建你的包。这个过程会创建一个临时的、隔离的构建环境。你的项目的构建过程(即使只是为了获取元数据)依赖于 toml
这个包(通常是 setup.py
内部需要读取 pyproject.toml
文件),但这个临时的构建环境里并没有预装 toml
,因此导致了 ModuleNotFoundError
,整个安装过程就失败了。
添加 pyproject.toml
更长期的解决方案是为你的项目添加一个 pyproject.toml
文件。在项目根目录(wheeledlab
目录)创建 pyproject.toml
文件,内容如下:
[build-system] requires = ["setuptools>=64.0.0", "wheel"] build-backend = "setuptools.build_meta"
然后重新安装:
pip install -e .
问题原因详细解释
这个方法很好地解决了我的问题,更详细地解释一下问题出现的原因:
pip
在构建你的包时,并不会使用你当前的 conda 环境 (WL)
,而是创建了一个临时的、隔离的“构建环境”(Isolated Build Environment)。
详细解释:
1.过去的方式(你所预期的行为)
- 在旧版本的
pip
和set编程客栈uptools
中,当你运行pip install
时,它会直接在你当前激活的环境中执行setup.py
脚本。 - 如果
setup.py
需要某个包(比如toml
),它会期望这个包已经存在于你的当前环境中。 - 这就是为什么我们以前会说“请先安装好所有构建依赖”。
2.现在的方式(实际发生的情况)
- 为了解决“构建依赖”和“运行时依赖”混淆不清、以及构建过程不稳定的问题,
Python
社区引入了PEP 517
和PEP 518
标准。
这个新标准的核心思想就是 构建隔离 (Build Isolation)。
当你运行 pip install -e .
时,pip 会执行以下步骤:
- 检查
pyproject.toml
:pip
首先会寻找pyproject.toml
文件来获取构建指令。 - 创建隔离环境:
pip
会在系统临时目录(比如/tmp/pip-build-env-xxxx/
)中创建一个全新的、非常迷你的虚拟环境。这个环境是完全独立的,它不包含你WL conda
环境中的任何包(除了最基础的Python
和pip
本身)。
安装构建依赖:
- 没有
pyproject.toml
时(你最初遇到的情况):pip
不知道这个隔离环境需要什么额外的包。它只安装了最基础的setuptools
和wheel
。因此,当你的setup.py
试图import toml
时,在这个“干净”的隔离环境里找不到它,从而报错ModuleNotFoundError
。 - 有
pyproject.toml
时(你解决后的情况):pip
读取了你的pyproject.toml
文件,看到了 [build-system] 下的requires = ["setuptools>=61.0", "toml"]
。pip
于是在那个隔离的构建环境中,首先执行pip install setuptools toml
。 - 执行构建:现在,隔离环境里已经有了
toml
包。pip
接着在这个准备好的环境中执行构建后端(setuptools.build_meta),这个过程就不会再因为缺少toml
而失败了。 - 安装项目:构建成功获取到元信息后,
pip
会将你的项目以可编辑模式安装回你原来的 WL` 环境。 - 清理:临时的隔离构建环境被删除。
总结与类比
你可以把这个过程想象成去一个高科技实验室做实验:
- 你的 Conda 环境 (WL):是你自己的、堆满各种工具和材料的个人工作室。你在里面安装了 toml。
- 隔离的构建环境:是一个无菌操作台(Clean Room)。你不能把你工作室里所有的东西都带进去,只能带清单上列出的必需品。
- pyproject.toml:就是那张必需品清单。
- 在你没有提供清单 (pyproject.toml) 的时候,pip 只带了最基础的工具进入无菌操作台。当实验(构建)需要用到 toml 这个特殊工具时,发现没带,实验失败。当你提供了清单 (pyproject.toml) 后,pip 在进入无菌操作台之前,先按照清单把 setuptools 和 toml 都准备好了。这样实验(构建)就能顺利进行了。
所以,即使你的个人工作室 (WL 环境) 里有 toml,但无菌操作台(隔离构建环境)里一开始是没有的。pyproject.toml 的作用就是告诉 pip 该往这个无菌操作台里准备些什么。
使用什么标准安装取决于什么
那么到底是用setup.py安装还是PEP 517/518标准安装取决于什么呢,Ubuntu系统版本,Python版本,setuptools版本还是什么
在 Python 生态中,setup.py
安装 vs. PEP 517/518 标准安装的选择取决于多个因素,但核心是由 pip
、setuptools
版本和项目配置共同决定的,而不是直接由 Ubuntu 系统版本或 Python 版本决定。
以下是详细分析:
1. 关键决定因素
因素 | 影响方式 |
---|---|
pip 版本 | 现代 pip(≥19.0)默认启用 PEP 517/518,旧版可能回退到 setup.py |
setuptools 版本 | 新版 setuptools(≥40.8.0)支持 PEP 517/518,旧版可能仅支持 setup.py |
项目配置 | 存在 pyproject.toml 时优先用 PEP 517/518,否则回退到 setup.py |
Python 版本 | 间接影响(Python ≥3.7 原生支持 PEP 517/518,但旧版可通过工具链支持) |
系统环境 | 几乎无直接影响(除非系统强制锁定了 pip/setuptools 版本) |
2. 具体行为规则
(1) 当项目有pyproject.toml时
- pip ≥19.0:强制使用 PEP 517/518 构建(隔离环境)。
[build-system] requires = ["setuptools>=61.0", "wheel"] # 必须显式声明构建依赖 build-backend = "setuptools.build_meta" # 使用 setuptools 作为后端
- 如果缺少
toml
等依赖,会报错(如你的案例)。 - 解决方案:在
pyproject.toml
的requires
中添加缺失的包。
(2) 当项目无pyproject.toml时
pip ≥19.0:回退到传统 setup.p编程客栈y
方式(非隔离环境)。
- 依赖主环境的包(可能引发冲突)。
- 逐步被弃用(会看到警告)。
3. 版本兼容性对照表
工具/配置 | 支持 PEP 517/518 的最低版本 | 备注 |
---|---|---|
pip | ≥19.0 (2019) | 旧版需升级:python -m pip ihttp://www.devze.comnstall -U pip |
setuptools | ≥40.8.0 (2018) | 新版推荐 ≥61.0 |
Python | ≥3.7 (官方支持) | 更低版本可通过工具链支持 |
pyproject.toml | 无版本要求 | 文件存在即触发 PEP 517/518 |
4. 如何强制选择安装方式?
(1) 强制使用传统setup.py(不推荐)
pip install -e . --no-use-pep517
- 绕过 PEP 517/518,直接运行
setup.py
(可能引发其他问题)。
(2) 强制使用 PEP 517/518
pip install -e . --use-pep517
- 即使无
pyproject.toml
也尝试用 PEP 517(可能失败)。
5. 为什么你的案例中toml在主环境无效?
根本原因:PEP 517/518 的隔离构建机制。
- 主环境的包(如已安装的
toml
)不会自动继承到临时构建环境。 - 必须通过
pyproject.toml
的requires
显式声明依赖。
6. 最佳实践建议
始终添加 pyproject.toml
- 即使项目简单,也明确声明构建js依赖(未来兼容性)。
[build-system] requires = ["setuptools>=64.0", "wheel"] build-backend = "setuptools.build_meta"
升级工具链
python编程 -m pip install -U pip setuptools wheel
避免混合使用新旧方式
- 不要同时依赖
setup.py
和pyproject.toml
的隐式行为。
总结
决定性因素:pyproject.toml
存在与否 + pip
/setuptools
版本。
系统/Python 版本:仅影响工具链的默认版本,不直接决定行为。
解决方案:显式声明依赖(pyproject.toml
)并保持工具链更新。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。
精彩评论