为缺少依赖声明的包(如scipy)构建轮子

16 投票
1 回答
85950 浏览
提问于 2025-04-18 10:41

我觉得在这里没什么区别,但我用的是Python 2.7。

我问题的一般部分是这样的:我为每个项目使用一个单独的virtualenv。我没有管理员权限,而且我也不想去动系统安装的包。自然,我想使用轮子(wheels)来加快在virtualenv之间升级和安装包的速度。那我该如何构建一个只在特定virtualenv中满足依赖关系的轮子呢?

具体来说,执行

pip wheel -w $WHEELHOUSE scipy

会失败,并显示

Building wheels for collected packages: scipy
  Running setup.py bdist_wheel for scipy
  Destination directory: /home/moritz/.pip/wheelhouse
  Complete output from command /home/moritz/.virtualenvs/base/bin/python -c "import setuptools;__file__='/home/moritz/.virtualenvs/base/build/scipy/setup.py';exec(compile(open(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" bdist_wheel -d /home/moritz/.pip/wheelhouse:
  Traceback (most recent call last):

  File "<string>", line 1, in <module>

  File "/home/moritz/.virtualenvs/base/build/scipy/setup.py", line 237, in <module>

    setup_package()

  File "/home/moritz/.virtualenvs/base/build/scipy/setup.py", line 225, in setup_package

    from numpy.distutils.core import setup

ImportError: No module named numpy.distutils.core

----------------------------------------
  Failed building wheel for scipy
Failed to build scipy
Cleaning up...

因为numpy并没有全局安装,而在一个已经安装了numpyvirtualenv中构建轮子是可以的,但让轮子依赖于特定virtualenv中的numpy版本似乎不是个好主意。

另外,pandas也依赖于numpy,它似乎会安装自己的一些numpy组件,但我不确定这是否是最佳解决方案。

我可以用--user安装numpy,然后用它来构建scipy的轮子。还有没有更好的选择呢?

1 个回答

15

问题描述

  • 有一个Python包(比如scipy),它依赖于其他包(比如numpy),但是setup.py文件没有声明这些依赖关系。
  • 如果当前环境中已经有了所需的包,那么构建这个包的轮子(wheel)是可以成功的。
  • 如果所需的包不可用,构建轮子就会失败。

注意:理想的解决方案是通过添加所需的包声明来修正损坏的setup.py。但这通常不可行,我们需要另寻他法。

解决方案:先安装所需的包

安装scipy(需要numpy)的过程分为两个步骤:

  1. 构建轮子
  2. 使用轮子来安装你需要的包

准备好你需要的轮子

这一步只需要做一次,以后可以重复使用。

  1. 配置好pip,这样就可以从轮子安装,设置好轮子目录,并与download-cachefind-links重叠,像下面这个pip.conf的例子:

    [global]
    download-cache = /home/javl/.pip/cache
    find-links = /home/javl/.pip/packages
    
    [install]
    use-wheel = yes
    
    [wheel]
    wheel-dir = /home/javl/.pip/packages
    
  2. 安装所有需要编译的包的系统库

  3. 为所需的包(numpy)构建一个轮子

    $ pip wheel numpy
    
  4. 设置虚拟环境(只需要做一次),激活它并在里面安装numpy

    $ pip install numpy
    

    一旦轮子准备好了,安装会很快。

  5. 在虚拟环境中为scipy构建一个轮子

    $ pip wheel scipy
    

    到这里,你的轮子目录就准备好了。

  6. 可以删除临时的虚拟环境,因为不再需要它。

在新的虚拟环境中安装

假设你已经创建了一个新的虚拟环境,并激活了它,想在里面安装scipy

直接从新的scipy轮子安装仍然会因为缺少numpy而失败。我们可以先安装numpy来解决这个问题。

$ pip install numpy

然后再安装scipy

$ pip install scipy

我想,这可以在一次调用中完成(但我没有测试过)

$ pip install numpy scipy

重复安装已验证版本的scipy

未来某个时候,可能会发布新的scipynumpy版本,而pip会尝试安装最新版本,但在你的轮子目录中没有这个轮子。

如果你对目前使用的版本满意,可以创建一个requirements.txt文件,列出你想要的numpyscipy的版本,并从中安装。

这样可以确保在真正使用之前,所需的包已经存在。

撰写回答