devpi适合需私有包上传与权限管理的混合场景,bandersnatch适合离线、轻量、纯镜像需求;二者核心差异在于架构定位与使用前提,选型应基于联网策略、存储容忍度及功能需求。

devpi 和 bandersnatch 是当前企业级私有 PyPI 镜像源最主流的两个技术路径,选哪个不取决于“谁更先进”,而取决于你是否允许内网机器首次安装时联网、能否接受初始存储占用、是否需要支持私有包上传。下面直奔实操要点。
devpi 适合需要缓存+私有包混合管理的场景
它不是纯镜像,而是带用户体系、索引隔离、权限控制的完整 PyPI 服务端。适合已有内部 Python 包要发布、或希望按项目/团队划分索引的团队。
-
devpi-server启动后默认监听3141端口,首次运行必须执行devpi-server --init初始化 root 用户和默认索引 - 不要直接用
root/pypi索引做业务分发——它默认是只读上游镜像;应创建新索引并配置--bases指向它,例如:devpi use root/pypi && devpi index -c myteam bases=root/pypi - 若用 Docker 部署,
/data/server目录必须挂载为持久卷,否则重启后所有用户、索引、上传包全丢 - 常见报错
ConnectionRefusedError: [Errno 111] Connection refused多因客户端未执行devpi use http://host:3141就直接调devpi login,顺序不能错
bandersnatch 更适合离线可用+空间可控的镜像需求
它是 PyPI 官方推荐的同步工具,目标是生成一个与 https://pypi.org/simple/ 行为一致的静态文件树。一旦同步完成,Web 服务器(如 Nginx)直接 alias 到 web/simple 即可,零依赖、零运行时。
- 配置中务必设置
python-package-names或include-packages,否则默认尝试同步全部 10TB+ 数据;例如只同步常用科学计算包:include-packages = numpy pandas torch scikit-learn -
bandersnatch mirror第一次运行会非常慢(数小时),且占用大量内存;建议在bandersnatch.conf中调低workers = 2,并确保磁盘有至少 2 倍包体积的空闲空间(压缩包解压后膨胀明显) - 同步完成后,Nginx 的
location /simple必须指向web/simple,而不是根目录;漏掉/simple后缀会导致 pip 报HTTP error 404 - 如果要用阿里云或清华源替代官方 master,改配置项
master = https://mirrors.aliyun.com/pypi/simple即可,但注意 bandersnatch 仅支持 simple API,不支持带认证或重定向的非标准源
pip 客户端配置必须匹配服务端路径结构
无论用哪种后端,最终 pip 能否正常工作,取决于 URL 是否能拼出合法的 /simple/xxx/ 和 /packages/ 路径。很多故障其实卡在这一步。
- devpi 默认提供
http://host:3141/root/pypi/+simple/—— 注意末尾是+simple,不是/simple;所以 pip 配置必须写成:pip config set global.index-url http://host:3141/root/pypi/+simple - bandersnatch + Nginx 提供的是标准
/simple/,所以 pip 配置是:pip config set global.index-url http://host/simple - Windows 上用
pip config设置后,配置文件落在%APPDATA%\pip\pip.ini;Linux/macOS 在~/.pip/pip.conf;手动编辑时,[global]段下必须有trusted-host = host,否则 HTTPS 跳转或 HTTP 源会失败 - 验证配置是否生效:运行
pip debug -v,看输出里index_urls是否为你设的地址
防火墙、SELinux 和存储监控是上线前最容易被跳过的三件事
它们不报错,但会让服务“看起来正常却无法使用”。
立即学习“Python免费学习笔记(深入)”;
- CentOS/RHEL 8+ 默认启用 firewalld,需显式放行端口:
sudo firewall-cmd --add-port=3141/tcp --permanent && sudo firewall-cmd --reload(devpi)或80/tcp(Nginx) - SELinux 在 enforcing 模式下会阻止 Nginx 读取 bandersnatch 的
web/目录,临时关闭验证:sudo setenforce 0;长期方案是打标签:sudo semanage fcontext -a -t httpd_sys_content_t "/path/to/mirror/web(/.*)?",再restorecon -Rv /path/to/mirror - bandersnatch 同步过程不检查磁盘空间,等填满才失败;建议在 cron 脚本开头加检查:
df -h /path/to/mirror | awk 'NR==2 {if ($5+0 > 90) exit 1}',超 90% 就退出同步
-i 就自动走内网源,且不会因为某台机器 pip 版本老、配置文件位置错、或者用了 conda 而失效”。这些细节散落在每个开发机、CI runner、Docker 构建上下文里,比服务端配置花的时间多得多。


















