使用setup.py和wheel安装包依赖项
我们正在使用一个内部托管的PyPI服务器(devpi-server
),这样我们可以存放一些大型软件包的二进制文件,这些软件包像scipy、matplotlib等,从源代码安装起来非常耗时。用pip install scipy
来安装这些软件包时,一切都很顺利,肯定是使用了我们创建的那个二进制文件(wheel)。但是,当我们使用任何一个内部开发的Python包,而这个包依赖于这些大型软件包时,运行python setup.py install|develop|test|whatever
就会出现以下错误:
No local packages or download links found for scipy
Traceback (most recent call last):
File "setup.py", line 136, in <module>
'develop': DevelopCommand
File "/usr/local/lib/python2.7/distutils/core.py", line 112, in setup
_setup_distribution = dist = klass(attrs)
File "/users/me/virtualenvs/devpi-test/lib/python2.7/site-packages/setuptools/dist.py", line 239, in __init__
self.fetch_build_eggs(attrs.pop('setup_requires'))
File "/users/me/virtualenvs/devpi-test/lib/python2.7/site-packages/setuptools/dist.py", line 263, in fetch_build_eggs
parse_requirements(requires), installer=self.fetch_build_egg
File "/users/me/virtualenvs/devpi-test/lib/python2.7/site-packages/pkg_resources.py", line 564, in resolve
dist = best[req.key] = env.best_match(req, self, installer)
File "/users/me/virtualenvs/devpi-test/lib/python2.7/site-packages/pkg_resources.py", line 802, in best_match
return self.obtain(req, installer) # try and download/install
File "/users/me/virtualenvs/devpi-test/lib/python2.7/site-packages/pkg_resources.py", line 814, in obtain
return installer(requirement)
File "/users/me/virtualenvs/devpi-test/lib/python2.7/site-packages/setuptools/dist.py", line 313, in fetch_build_egg
return cmd.easy_install(req)
File "/users/me/virtualenvs/devpi-test/lib/python2.7/site-packages/setuptools/command/easy_install.py", line 587, in easy_install
raise DistutilsError(msg)
distutils.errors.DistutilsError: Could not find suitable distribution for Requirement.parse('scipy')
而使用easy_install
时:
$ easy_install scipy
Searching for scipy
Reading http://pypi.internal.example.com/us/base/+simple/scipy/
No local packages or download links found for scipy
error: Could not find suitable distribution for Requirement.parse('scipy')
如果我抓取它正在查看的URL,我得到:
$ curl http://pypi.internal.example.com/us/base/+simple/scipy/
<html>
<head>
<title>us/base: links for scipy</title></head>
<body>
<h1>us/base: links for scipy</h1>
<form action="http://pypi.internal.example.com/us/base/+simple/scipy/refresh" method="post"><input name="refresh" type="submit" value="Refresh PyPI links"/></form>
us/external <a href="../../../external/+f/c48/5006bc28a8607/scipy-0.14.0-cp27-none-linux_x86_64.whl#md5=c485006bc28a8607b2fc1331df452dc1">scipy-0.14.0-cp27-none-linux_x86_64.whl</a><br/>
</body></html>
如果我请求输出中列出的那个URL,我会得到这个二进制文件:
$ curl --silent 'http://pypi.internal.example.com/us/external/+f/c48/5006bc28a8607/scipy-0.14.0-cp27-none-linux_x86_64.whl#md5=c485006bc28a8607b2fc1331df452dc1' \
| file -
/dev/stdin: Zip archive data, at least v2.0 to extract
1 个回答
1
首先,问题中提到的情况并不依赖于使用 devpi
,在任何 PyPI 服务器上都能重现,包括主仓库 pypi.org。举个例子:
# setup.py
from setuptools import setup
setup(name='spam', install_requires=['vprof>0.37'])
(你可以用任何其他只包含轮子文件的包来替代 vprof
)
测试一下:
$ pip install --upgrade "setuptools<38.2.0"
...
Successfully installed setuptools-38.1.0
$ python setup.py install
running install
running bdist_egg
running egg_info
writing spam.egg-info/PKG-INFO
...
Processing dependencies for spam==0.0.0
Searching for vprof>0.37
Reading https://pypi.python.org/simple/vprof/
No local packages or working download links found for vprof>0.37
error: Could not find suitable distribution for
Requirement.parse('vprof>0.37')
哎呀,当你把一个只包含二进制文件的包声明为构建依赖时,情况就更糟了:
setup(name='spam', setup_requires=['vprof>0.37'])
现在所有的构建和打包命令都会失败,因为它们无法下载构建依赖。
这个问题完全取决于你使用的 setuptools
版本。自2017年11月26日和版本38.2.0起,setuptools
支持获取和安装轮子依赖,所以如果你仍然遇到这个问题:
升级 setuptools
较新的操作系统版本应该已经自带了较新的 setuptools
。比如,Ubuntu 18.04 默认安装的是 setuptools==39.0.1
(链接)。如果你仍然安装的是旧版的 setuptools
,大多数情况下它是由系统的包管理器管理的,所以你不应该通过 pip
来更新它。你可以用户安装一个额外的 setuptools
副本
$ pip install --user --upgrade "setuptools>=38.2.0"
或者使用虚拟环境来处理这个问题。