python 告诉pip包为其自己的安装和所有install_requires安装安装生成依赖项

icnyk63a  于 2023-02-28  发布在  Python
关注(0)|答案(2)|浏览(215)

我正在安装一个包,它的依赖项需要在它的setup.py中导入numpy。它还需要Cython来正确地构建这个依赖项。这个依赖项是scikit-learn==0.21.2。下面是我自己的包mypkgnamesetup.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安装mypkgnamenumpyCython在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的日志,似乎不是这样。
我尝试事先安装setuptoolsCython

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的开始安装到最后安装numpyCythonsetuptools?我希望numpyCythonsetuptools包在mypkgname的安装和install_requires包的每次安装中都可用。
因为它将是一个部署在pypi上的包,我不希望人们在运行pip install mypkgname时安装pip以外的任何东西。

rvpgvaaj

rvpgvaaj1#

pip使用build Isolation来构建软件包,也就是说,它会将构建依赖项安装到一个单独的虚拟环境中,构建一个软件包并移除隔离的venv,因此构建依赖项(在您的例子中是Cython和numpy)会与隔离的venv沿着被移除。
您可以禁用隔离,但更好、更正确的方法是声明依赖项两次--作为构建依赖项和运行时依赖项:

install_requires=[
        "scikit-learn==0.21.2",
        "Cython",
        "numpy>=1.11.0,<=1.22.4",
    ],

构建软件包pip/setuptools时,请将依赖项列表包含到wheel中,它们将随软件包沿着自动安装到目标环境中。

i1icjdpr

i1icjdpr2#

现在,pip 允许构建(从 sdistwheel)在隔离的环境中进行。在每个构建环境中,安装在[build-system]中声明的构建需求。构建环境不会重用。每个需要构建步骤的依赖项将获得自己的临时构建环境。
我的猜测是,您的项目的一个依赖项(直接或间接)没有正确地声明其构建需求(也许这个依赖项甚至根本没有自己的pyproject.toml文件)。
您的项目声明了对scikit-learn==0.21.2的直接依赖,您还提到您使用的是Python 3.8,在下面的链接中我们可以看到 PyPI 没有任何scikit-learn==0.21.2的Python 3.8版本的内置发行版(wheels):

  • https://pypi.org/project/scikit-learn/0.21.2/#files

不过有一个源代码发行版(sdist.tar.gz),我们可以在下面的链接中看到,这个 sdist 不包含任何pyproject.toml文件,因此无法声明其构建依赖关系:

相关问题