引言
在跨地域部署、离线私有网或海量 CI/CD 任务中,Python 依赖下载常因外网抖动而失败。与其在关键时刻坐等超时,不如提前把依赖全部缓存到本地,再让安装过程只读本地文件。本篇文章用 5W2H 框架全面拆解这一需求,并给出可复制的脚本与最佳实践。
5W2H 分析
Who -- 谁需要?
- 后端与数据科学开发者
- 维护离线生产环境的运维/DevOps
- 频繁重建镜像的 CI/CD 平台
What -- 需求是什么?
在网络良好时一次性下载 requirements.txt 指定的所有包及其递归依赖,存放到本地或共享磁盘;后续安装时只访问本地文件而不访问 PyPI。
Why -- 为什么要这样做?
- 网络不稳定或受限,线上容器拉取超时
- 大规模并发安装导致外网带宽瓶颈
- 某些合规环境要求禁止直接联外网
When -- 何时执行?
- 每次修改 requirements.txt 后
- 例行构建镜像/制品前
- 离线环境部署窗口开启前
Where -- 本地缓存放哪?
- 项目根目录下
./packages
- 多项目共享的 NFS/对象存储
- 公司制品库 (Artifactory、Nexus) 作为私有 PyPI
How -- 如何实现?
bash
# 1. 批量下载
pip download -r requirements.txt -d ./packages
# 2. 离线安装
pip install --no-index --find-links=./packages -r requirements.txt
关键参数
-r
:读取依赖列表-d
:下载目录--no-index
:禁用官方索引--find-links
:额外查找路径,可写多个
How much -- 成本/收益?
- 时间:一次性下载 ≈ 在线安装时间,但后续安装几乎瞬间完成
- 空间:以机器学习项目为例,200 MB--1 GB;可用
du -sh packages
评估 - 维护:随 requirements 变动更新;旧版本可定期清理或归档
实战步骤
1. 初始化脚本
将下列内容保存为 prepare_packages.sh
,加执行权限:
bash
#!/usr/bin/env bash
set -e
PKG_DIR=${1:-./packages}
REQ_FILE=${2:-requirements.txt}
mkdir -p "$PKG_DIR"
echo "Downloading dependencies to $PKG_DIR ..."
pip download -r "$REQ_FILE" -d "$PKG_DIR"
echo "Download finished."
执行 ./prepare_packages.sh
即可刷新缓存。
2. 离线安装脚本
bash
#!/usr/bin/env bash
set -e
PKG_DIR=${1:-./packages}
REQ_FILE=${2:-requirements.txt}
pip install --no-index --find-links="$PKG_DIR" -r "$REQ_FILE"
在 Dockerfile 中可写成:
dockerfile
COPY packages /opt/packages
RUN pip install --no-index --find-links=/opt/packages -r requirements.txt
3. 自动更新策略
- GitLab CI:在
before_script
执行下载脚本并缓存packages
目录 - Jenkins:利用定时任务
H 3 * * *
检测 requirements 变化并触发更新 - 本地开发:结合
pre-commit
钩子,每次提交变化自动增量下载
4. 常见问题
场景 | 处理方式 |
---|---|
私有包 | 在 pip download 时添加私有源 -i https://pypi.xxx.com/simple |
平台无 pip download | 升级到 pip ≥ 9.0,或用 pip wheel + pip install --no-index |
多平台 ABI 不兼容 | 预先在目标系统上执行下载,或限制 --platform --python-version 参数 |
5. 扩展:搭建轻量私有 PyPI
若想多人共享,可以用 pypiserver
或 devpi
启动一个内网 PyPI,只需把 packages
目录做为数据根目录即可:
bash
pip install pypiserver
pypi-server -p 8080 packages
随后在安装命令中改为:
bash
pip install -i http://pypi.local:8080/simple -r requirements.txt
结语
通过 5W2H 的梳理,我们从动机、场景到实施细节全链路覆盖了"提前缓存 Python 依赖"的方案。核心只需两条命令,却能显著提升部署韧性与速度。将其纳入日常的 CI/CD 环节,并配合私有镜像或对象存储,就能在任何网络环境下从容交付。