实际开发中,我们的项目部署环境可能是封闭的内网环境,无法直接使用pip install -r requirement.txt这种方式安装项目依赖包,这时pip download这个犀利的工具就要发光发热了
- 使用pip download在一个可以连接外网的环境下载整个项目的依赖包,将要安装的
tensorflow
以及所有依赖都下载到本地
pip download tensorflow
也可以通过
pip download -r requirements.txt -d 目标文件夹 -i https://pypi.douban.com/simple/
将requirements.txt
文件中的依赖下载到目标文件夹,同时指定源。
然后拷贝到目标offline机器的某个目录(比如/offline_package_dir),并通过如下命令安装:
pip install --no-index --find-links ./offline_package_dir tensorflow
看起来很美好,但如果两台机器架构不一样,则十分痛苦。 根据online和offline机器的架构是否相同(即OS是否一样,Python版本是否一样),分别如下:
online和offline机器架构完全相同
这种情况比较简单:
- 直接在online机器执行如下命令,下载所有依赖package到当前目录:
pip download tensorflow
如果下载速度慢,可以指定源:
pip download tensorflow -i https://pypi.douban.com/simple/
- 将目录内容拷贝到目标offline机器(比如/offline_package_dir),并目标offline机器执行
pip install --no-index --find-links=file:/offline_package_dir tensorflow
由于两个机器架构完全一样,因此download的package在目标机器一定可以安装。
online和offline机器架构不同
这种情况比较复杂,因为机器架构不同,直接用pip download tensorflow
下载的package在目标机器很可能不适用。
以TensorFlow为例,PyPI上看到的wheel文件,至少根据OS、Python版本以及CPU架构做了区分:
PyPI上package有好几种格式:
- 源文件(一般是.tar.gz或.zip文件,用pip安装,与机器架构无关,但某些package可能涉及到C/C++编译)
- wheel文件(二进制文件,拓展名为.whl,用pip安装,无需编译,但与机器架构相关)
- .egg文件(二进制文件,用easy_install安装,无需编译,但与机器架构相关)
不幸的是PiPY并没有规定一个package必须提供的安装格式,有的只有wheel没有源文件,有的只有源文件没有wheel或egg。 这也是导致下文pip download失败的原因。
可以在执行download命令时,添加参数,指明要下载package对应的架构, 例如在macOS上为offline的linux下载TensorFlow,目标机器上装了Python2.7,64位系统。
pip download \
--only-binary=:all: \ # 只下载二进制package(即wheel或egg)
--platform linux_x86_64 \ # 说明是linux 64位架构
--python-version 27 \ # Python 2.7
--implementation cp \ # cpython,一般都是这个
--abi cp27mu
tensorflow # 要下载的package名
刚开始都正常,但下载到一半的时候就报错:
Could not find a version that satisfies the requirement absl-py>=0.1.6 (from tensorflow) (from versions: )
No matching distribution found for absl-py>=0.1.6 (from tensorflow)
这是因为参数--only-binary=:all:
只下载二进制版,而tensorflow依赖的absl-py在PyPI中只有.tar.gz的源码版,没有二进制版。
那能不能不限制--only-binary=:all:
?不行,一旦指定具体的架构,就必须设置--only-binary=:all:
,或者不下载依赖,这是pip install用法的规定,可参考官方Reference: https://pip.pypa.io/en/stable/reference/pip_download/
归根结底,是pip install命令,一旦指定了平台相关的参数,就只能下载二进制package。
到这个地步,若不想手工做,只有一条路:保证online和offline机器架构一样。 所谓架构一样,其实就是四个参数一样:--platform
, --python-version
, --implementation
, and --abi
- platform即操作系统,这个可以通过虚拟机或docker解决
- python-version,可以通过pipenv解决
- implementation,目前一般只考虑cpython
- abi,通过虚拟机或docker吧
推荐方法:pyenv+docker
经过上面的分析总结,首先需要让online和offline机器架构一样。
如果online和offline的机器架构完全一样:OS一样、Python版本一样,非常简单:
- 先在online机器执行download,下载所有依赖package到当前目录:
pip download tensorflow
- 将目录内容拷贝到目标offline机器(比如/offline_package_dir),并目标offline机器执行:
pip install --no-index --find-links=file:/offline_package_dir tensorflow
如果online和offline的机器架构不一样:
- 仅Python版本不一样,则可以通过
pyenv
创建指定版本的Python,然后切换版本,再执行上面的操作。 - 如果操作系统不一样,可以通过docker,安装指定版本的Python,然后再执行上面的操作。
pip 下载依赖包
例如要下载gensim
包,就可以通过pip download -d 目标文件夹 包名
进行下载。
因为我当前的Python版本是3.9.12
所以他下载的对应的依赖也是基于Python3.9的。如果要下载其他版本,需要切换到对应的Python版本。