2、Python pip离线安装:pip download命令详解、生成requirements.txt、离线包迁移与安装
说实话,做运维这些年,最怕的就是客户现场没网。尤其是Python项目,一上来就要装几十个依赖包,环境还五花八门。我刚开始那会儿,傻乎乎地一个个去PyPI上扒源码包,结果版本对不上,折腾到半夜。后来才发现,pip本身就有个宝藏命令——pip download,专门解决离线安装的问题。
今天我就把这个流程掰开揉碎了讲给你听。说白了就三步:生成清单 → 下载包 → 迁移安装。咱们一个一个来。
2.1 生成requirements.txt
这是离线安装的第一步。你得先知道自己项目到底依赖了哪些包。我见过不少新手,直接在项目里装了一堆包,最后也不知道哪些是真正用到的。嗯,这里有个小技巧:用虚拟环境隔离项目依赖。
生成方式很简单,在项目根目录下执行:
# 导出当前环境的所有包
pip freeze > requirements.txt
但要注意,pip freeze会导出所有已安装的包,包括那些间接依赖。我个人更推荐用pipreqs这个工具,它只扫描项目代码里真正import的包:
# 安装pipreqs
pip install pipreqs
# 扫描当前目录,生成requirements.txt
pipreqs . --encoding=utf8 --force
为什么要用--force?因为如果已经存在requirements.txt,它会覆盖。我在项目中遇到过好几次,忘记加这个参数,结果生成失败,还以为是工具坏了。
生成的requirements.txt长这样:
flask==2.3.2
requests==2.31.0
numpy==1.24.3
pandas==2.0.3
每一行是包名==版本号的格式。你想想看,有了这个文件,后面的事情就顺了。
2.2 pip download命令详解
有了requirements.txt,接下来就是下载。核心命令就是pip download。它的作用是把指定的包下载到本地目录,但不安装。
最基本的用法:
# 下载requirements.txt里列出的所有包
pip download -r requirements.txt -d ./offline_packages
这里-d指定下载目录,./offline_packages是我习惯用的名字。你随便起,但别用中文路径,有些包在Windows上会出问题——我曾经踩过这个坑。
但光这样还不够。你想想看,这些包本身可能还有依赖。比如你装pandas,它依赖numpy,numpy又依赖一些底层库。如果不处理这些间接依赖,离线安装时照样报错。
所以,我建议加上--no-deps参数?不,恰恰相反。我们要下载所有依赖,包括间接的:
# 下载所有依赖(包括间接依赖)
pip download -r requirements.txt -d ./offline_packages --no-binary :all:
--no-binary :all:的意思是只下载源码包(.tar.gz或.zip),不下载wheel包。为什么?因为源码包跨平台兼容性更好。我在项目中遇到过,有些wheel包是针对特定Python版本或操作系统的,换台机器就装不上。源码包虽然安装慢一点,但稳。
当然,如果你确定目标机器和当前机器环境完全一致(比如都是CentOS 7 + Python 3.9),那用wheel包更快:
# 下载wheel包(更快,但注意平台兼容性)
pip download -r requirements.txt -d ./offline_packages --only-binary=:all:
下载完成后,./offline_packages目录里会有一堆文件。你可以用ls看看:
$ ls ./offline_packages/
Flask-2.3.2.tar.gz
requests-2.31.0.tar.gz
numpy-1.24.3.tar.gz
pandas-2.0.3.tar.gz
...(还有一堆间接依赖的包)
2.3 离线包迁移与安装
包下载好了,怎么搬到目标机器上?我一般用U盘或者scp。如果是内网环境,搭个简单的HTTP服务器也行。但最保险的方式还是U盘——物理隔离的网络,你懂的。
到了目标机器上,安装命令也很简单:
# 从本地目录安装所有包
pip install --no-index --find-links ./offline_packages -r requirements.txt
解释一下参数:
--no-index:告诉pip不要去PyPI上找包,只从本地找。这个参数不加的话,pip还是会尝试联网,那就白忙活了。--find-links:指定本地包的路径。可以是目录,也可以是文件路径。-r requirements.txt:指定要安装哪些包。
执行后,pip会从./offline_packages目录里找对应的包,然后安装。整个过程不需要网络。
numpy==1.24.3,但下载的却是numpy-1.24.2.tar.gz。所以,一定要保证requirements.txt和下载的包版本完全对应。我的做法是:下载完成后,用pip list检查一下版本,再更新requirements.txt。
还有一个常见问题:如果目标机器上没有Python环境怎么办?那就得先装Python。但那是另一个话题了,今天先不展开。
2.4 完整流程总结
我把整个流程画了个图,方便你理解:
嗯,整个流程就是这样。说白了,就是先列清单、再采购、最后搬运安装。和你在网上买东西差不多,只不过这里买的是Python包。
最后再啰嗦一句:离线安装最怕的就是版本冲突。我建议你在开发机上先测试一遍,确保所有包都能正常安装和运行,再打包迁移。别问我怎么知道的——有一次我图省事,直接打包就跑了,结果到客户现场发现有个包版本不对,现场改代码,那叫一个狼狈。
好了,这一节就到这里。记住这个流程,以后遇到离线环境,你也能从容应对。