我正在安装一个包,它的依赖项需要在它的setup.py
中导入numpy
。它还需要Cython
来正确地构建这个依赖项。这个依赖项是scikit-learn==0.21.2
。下面是我自己的包mypkgname
的setup.py
:
from setuptools import find_packages, setup
import Cython # to check that Cython is indeed installed
import numpy # to check that numpy is indeed installed
setup(
name="mypkgname",
version="0.1.0",
packages=find_packages("src", exclude=["tests"]),
package_dir={"": "src"},
install_requires=[
"scikit-learn==0.21.2"
],
)
为了确保在pip
安装mypkgname
时numpy
和Cython
在mypkgname的setup.py
中可用,我按如下方式设置pyproject.toml
:
[build-system]
requires = ["setuptools>=40.8.0", "Cython", "numpy>=1.11.0,<=1.22.4", "wheel"]
build-backend = "setuptools.build_meta"
运行pip install -e .
后,mypkgname的setup.py
中的import numpy; import Cython
可以工作,但scikit-learn==0.21.2
安装中的import Cython
无法:
File "/home/vvvvv/.pyenv/versions/3.8.12/envs/withingswpm04-38/lib/python3.8/site-packages/numpy/distutils/misc_util.py", line 1016, in get_subpackage
config = self._get_configuration_from_setup_py(
File "/home/vvvvv/.pyenv/versions/3.8.12/envs/withingswpm04-38/lib/python3.8/site-packages/numpy/distutils/misc_util.py", line 958, in _get_configuration_from_setup_py
config = setup_module.configuration(*args)
File "sklearn/utils/setup.py", line 8, in configuration
from Cython import Tempita
ModuleNotFoundError: No module named 'Cython'
error: subprocess-exited-with-error
我不明白为什么Cython
可以用于安装我自己的mypkgname,而不能用于安装mypkgname的install_requires
包。好像Cython
在安装install_requires
包之前被卸载了(?)。但是通过检查pip install -v
的日志,似乎不是这样。
我尝试事先安装setuptools
和Cython
:
pip install setuptools Cython
pip install -e .
它工作了。事实上,scikit-learn==0.21.2
需要这两个已经安装的软件包才能正确安装。但是,我尝试安装的scikit-learn版本没有在pyproject.toml
中指定任何Cython
构建要求。这里有一个scikit-learn软件包setup.py
的链接。
如果我只是安装setuptools
,它仍然会失败,并出现与第一个示例(ModuleNotFoundError: No module named 'Cython'
)相同的错误。
- 注:**
- 我被迫使用scikit-learn的这个特定版本是出于一些断章取义的原因。
- 我使用的是Python 3.8.12、pip 23.0.1和Ubuntu 22.04,我用pyenv和virtualenv做了同样的尝试,我也用
pip install -v -U --no-cache-dir
做了同样的尝试。
如何告诉mypkgname我需要从pip install
的开始安装到最后安装numpy
、Cython
和setuptools
?我希望numpy
、Cython
和setuptools
包在mypkgname
的安装和install_requires
包的每次安装中都可用。
因为它将是一个部署在pypi上的包,我不希望人们在运行pip install mypkgname
时安装pip
以外的任何东西。
2条答案
按热度按时间rvpgvaaj1#
pip使用build Isolation来构建软件包,也就是说,它会将构建依赖项安装到一个单独的虚拟环境中,构建一个软件包并移除隔离的venv,因此构建依赖项(在您的例子中是Cython和numpy)会与隔离的venv沿着被移除。
您可以禁用隔离,但更好、更正确的方法是声明依赖项两次--作为构建依赖项和运行时依赖项:
构建软件包
pip
/setuptools
时,请将依赖项列表包含到wheel中,它们将随软件包沿着自动安装到目标环境中。i1icjdpr2#
现在,pip 允许构建(从 sdist 到 wheel)在隔离的环境中进行。在每个构建环境中,安装在
[build-system]
中声明的构建需求。构建环境不会重用。每个需要构建步骤的依赖项将获得自己的临时构建环境。我的猜测是,您的项目的一个依赖项(直接或间接)没有正确地声明其构建需求(也许这个依赖项甚至根本没有自己的
pyproject.toml
文件)。您的项目声明了对
scikit-learn==0.21.2
的直接依赖,您还提到您使用的是Python 3.8,在下面的链接中我们可以看到 PyPI 没有任何scikit-learn==0.21.2
的Python 3.8版本的内置发行版(wheels):不过有一个源代码发行版(sdist,
.tar.gz
),我们可以在下面的链接中看到,这个 sdist 不包含任何pyproject.toml
文件,因此无法声明其构建依赖关系:可能的解决方法:
scikit-learn==0.21.2
有适用于Python 3.5到3.7的轮子,所以您可以同意使用其中一个Python解释器。scikit-learn
版本,它的 PyPI 拥有与Python 3.8兼容的 wheels。scikit-learn==0.21.2
wheel。python -m pip install --no-build-isolation --editable .
的代码来禁用 pip 的“build isolation”特性。