如何让pip在安装自定义包及依赖全程提供numpy、Cython构建依赖?
问题根源
pip的构建隔离机制会为每个待安装的包创建独立临时环境:你在pyproject.toml里指定的构建依赖只作用于mypkgname自身的构建流程,而scikit-learn==0.21.2作为你的包的运行依赖,它的构建会在单独的隔离环境中进行——由于这个旧版本的scikit-learn没有通过pyproject.toml声明自身的构建依赖(Cython、numpy),所以pip无法自动为它安装这些依赖,导致构建失败。
方法1:禁用构建隔离(快速 workaround)
执行安装时添加--no-build-isolation参数,让pip在当前环境(或虚拟环境)中统一处理所有构建依赖:
pip install -e . --no-build-isolation
这个方法无需修改代码,但需要用户记住额外参数,适合临时测试或内部使用。
方法2:在setup.py中预安装scikit-learn的构建依赖
在mypkgname的setup.py开头添加逻辑,先安装scikit-learn构建必需的Cython和numpy,再声明运行依赖:
from setuptools import setup import subprocess import sys # 预安装scikit-learn 0.21.2的构建依赖 def install_sklearn_build_deps(): subprocess.check_call( [sys.executable, "-m", "pip", "install", "Cython>=0.28.5", "numpy>=1.11.0"] ) install_sklearn_build_deps() setup( name="mypkgname", install_requires=[ "scikit-learn==0.21.2" ], # 其他包配置项... )
这样在处理install_requires之前,会先把scikit-learn需要的构建依赖安装到环境中,后续安装scikit-learn时就能正常找到这些包。
方法3:将构建依赖转为运行依赖(简单直接)
把Cython和numpy添加到mypkgname的install_requires中,同时保留pyproject.toml里的构建依赖配置:
pyproject.toml
[build-system] requires = ["setuptools", "Cython>=0.28.5", "numpy>=1.11.0"] build-backend = "setuptools.build_meta"
setup.py
from setuptools import setup setup( name="mypkgname", install_requires=[ "Cython>=0.28.5", "numpy>=1.11.0", "scikit-learn==0.21.2" ], # 其他包配置项... )
pip会按顺序安装这些依赖,先装Cython和numpy,再装scikit-learn,此时scikit-learn构建时就能找到所需依赖。缺点是会把构建依赖变成你的包的运行时依赖,如果你的包本身不需要它们运行,这会增加不必要的依赖体积。
避坑提示
- 不要使用已被弃用的
setup_requires参数:setuptools官方已不再推荐该参数,它的依赖安装机制存在缺陷,且pip优先遵循pyproject.toml的构建配置。
内容的提问来源于stack exchange,提问作者vvvvv

