Pip Cache
导言
VeRL场景开发时,安装包特别多和复杂:
- CANN
- torch\torch_npu
- vllm\vllm_ascend
- MindSpeed\megatron
- transformer
开发时还要pip install -e . 还要修改代码。
传统的思路是docker镜像或者conda打大包,但是这种包一个就是20GB+,但是这是商发时的策略,开发时即使只是修改一行,但是还是要重新出一个20GB大包。
思路是借助并加速pip的原子化构建:
- 在内网服务器上建立一个pip包缓存站,
- 不仅能缓存官方包,
- 自己修改的代码包也能提交。
- 最终实现,除了CANN安装,其余pip包,一行
pip intall -r requirements.txt就行。
DevPI¶
DevPI 不仅仅是一个私有索引,它是一个功能完备的 PyPI 仓库和分发系统。
核心优势¶
- 缓存代理 (Caching Proxy): 这是你最关心的功能。DevPI 默认配置了一个名为
:root/pypi的上游索引,它会自动从官方 PyPI 下载包并将其缓存在本地。这样,第二次请求同一个包时,DevPI 会直接从本地提供,大大加快速度并支持离线安装。 - 多索引管理 (Multi-Index Management): DevPI 允许创建多个虚拟索引(Index)。你可以基于上游 PyPI 创建自己的私有索引(例如
:root/dev),也可以将这些索引链接起来,实现开发、测试、生产环境的包隔离。 - 上传私有包 (Private Packages): 你可以使用
devpi upload命令将自己的私有包上传到特定的索引中。 - 易于部署: 虽然功能强大,但 DevPI 基于 Python,安装和初始化非常便捷。
DevPI 服务端搭建¶
1. 安装 DevPI 及其依赖¶
在 Windows 的命令行或 PowerShell 中执行安装命令:
# -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host=mirrors.aliyun.com
pip install devpi-server devpi-client
# DevPI 在 Windows 上可能需要额外的依赖
pip install devpi-web
2. 初始化 DevPI 服务器¶
DevPI 需要一个本地目录来存放数据和缓存。
# 切换到一个你希望存储 DevPI 数据的目录
cd D:\DevPI_Data
# 初始化 DevPI 数据库和存储结构
(base) D:\DevPI_Data>devpi-init --serverdir D:\DevPI_Data
2025-12-09 20:25:43,692 INFO NOCTX Loading node info from D:\DevPI_Data\.nodeinfo
2025-12-09 20:25:43,692 INFO NOCTX generated uuid: c095ddcc22e24f09a58cefde30f37754
2025-12-09 20:25:43,692 INFO NOCTX wrote nodeinfo to: D:\DevPI_Data\.nodeinfo
2025-12-09 20:25:43,696 INFO NOCTX DB: Creating schema
2025-12-09 20:25:43,741 INFO [Wtx-1] setting password for user 'root'
2025-12-09 20:25:43,746 INFO [Wtx-1] created user 'root'
2025-12-09 20:25:43,746 INFO [Wtx-1] created root user
2025-12-09 20:25:43,746 INFO [Wtx-1] created root/pypi index
2025-12-09 20:25:43,749 INFO [Wtx-1] fswriter0: committed at 0
3. 启动 DevPI 服务器¶
curl 验证
(base) root@localhost ~ [12:54:58]
> curl -v http://80.253.12.220:3141/root/pypi/
* Trying 80.253.12.220:3141...
* Connected to 80.253.12.220 (80.253.12.220) port 3141 (#0)
> GET /root/pypi/ HTTP/1.1
> Host: 80.253.12.220:3141
> User-Agent: curl/7.87.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 302 Found
< Content-Length: 203
< Content-Type: text/html; charset=UTF-8
< Date: Tue, 09 Dec 2025 08:55:41 GMT
< Location: http://80.253.12.220:3141/root/pypi
< Server: waitress
< X-Devpi-Api-Version: 2
< X-Devpi-Master-Uuid: bb08ed26164142f189ff8cfb7970fb73
< X-Devpi-Primary-Uuid: bb08ed26164142f189ff8cfb7970fb73
< X-Devpi-Serial: 0
< X-Devpi-Server-Version: 6.17.0
< X-Devpi-Uuid: bb08ed26164142f189ff8cfb7970fb73
<
<html>
<head>
<title>302 Found</title>
</head>
<body>
<h1>302 Found</h1>
The resource was found at http://80.253.12.220:3141/root/pypi; you should be redirected automatically.
</body>
* Connection #0 to host 80.253.12.220 left intact
</html>#
4. 删除过量缓存¶
- DevPI只支持单个包删除
delete, 不支持最近最少使用,最大包删除之类的批量操作 - DevPI也没有自动删除机制,文件会永久保存在一个文件的hash目录下。
- 文件存储位置
D:\DevPI_Data\+files\root\pypi\+f\efd\28d4e9cd7d7a8 - 推荐一个常用场景使用一个目录,比如
root/verl,
客户端使用¶
一旦你的 DevPI 服务器(无论是运行在 Windows、Linux 还是 WSL/Docker 上)启动并可通过网络访问,Linux 客户端就可以通过 devpi-client 或直接使用 pip 进行配置。
假设你的 DevPI 服务器地址是 http://<Server_IP>:3141。
1. 使用 devpi-client (推荐配置)¶
devpi-client 工具可以方便地管理索引和登录,推荐在客户端安装。
步骤一:安装客户端¶
步骤二:指定服务器地址¶
使用 devpi use 命令来告诉客户端 DevPI 服务器的地址:
# devpi use http://<Server_IP>:3141
> devpi use http://80.253.12.220:3141
Warning: insecure http host, trusted-host will be set for pip
using server: http://80.253.12.220:3141/ (not logged in)
no current index: type 'devpi use -l' to discover indices
/data/t00906153/.config/pip/pip.conf: no config file exists
/data/t00906153/.config/uv/uv.toml: no config file exists
/data/t00906153/.pydistutils.cfg: no config file exists
/data/t00906153/.buildout/default.cfg: no config file exists
always-set-cfg: no
步骤三:登录并创建/选择索引¶
服务端serverdir改变,密码会归零,换源也会消失
- DevPI 默认有一个
root用户,登录默认没密码直接回车,然后-m修改密码:
(base) PS C:\Users\t00906153> devpi login root
password for user root at http://localhost:3141/:
logged in 'root', credentials valid for 10.00 hours
(base) PS C:\Users\t00906153> devpi user -m root password=yahaha
/root changing password: ********
user modified: root
- 使用默认的缓存代理索引 (
:root/pypi): 这个索引是 DevPI 自动生成的,它会缓存所有从官方 PyPI 下载的包。你不需要额外配置。
步骤四:换源¶
# 清华源 https://pypi.tuna.tsinghua.edu.cn/simple
(tsj_debug_pypi-server) root@worker-02 ~ [07:58:42]
> devpi index root/pypi mirror_url=http://mirrors.aliyun.com/pypi/simple/
/root/pypi mirror_url=http://mirrors.aliyun.com/pypi/simple/
http://80.253.12.220:3141/root/pypi?no_projects=:
type=mirror
volatile=False
mirror_url=http://mirrors.aliyun.com/pypi/simple/
mirror_web_url_fmt=https://pypi.org/project/{name}/
title=PyPI
2. 直接使用 pip¶
如果不想安装 devpi-client,可以直接修改 pip 的配置,指向 DevPI 服务器。
安装官方 PyPI 已有的包 (享受缓存)¶
要让 pip 从你的 DevPI 缓存代理下载包,你需要使用 --index-url 参数,并指向你要使用的索引,通常是默认的 :root/pypi 索引:
# pip install requests --index-url http://<Server_IP>:3141/root/pypi/ --trusted-host <Server_IP>
pip install vllm-ascend==0.11.0rc0 -i http://80.253.12.220:3141/root/pypi --trusted-host 80.253.12.220
固化到配置里
由于IP会变,使用环境变量PIP_INDEX_URL
IP=80.253.12.220
PORT=8082
http_proxy="http://p_atlas:proxy%40123@$IP:$PORT"
export http_proxy=$http_proxy
export https_proxy="http://p_atlas:proxy%40123@$IP:$PORT"
#export http_proxy="http://$IP:8080"
#export https_proxy="http://$IP:8080"
export no_proxy=127.0.0.1,localhost,local,.local,$IP
export GIT_SSL_NO_VERIFY=1
export PIP_INDEX_URL=http://$IP:3141/root/pypi/
export PIP_TRUSTED_HOST=$IP
git config --global http.sslVerify false
git config --global https.proxy https://p_atlas:proxy%40123@$IP:$PORT
git config --global http.proxy http://p_atlas:proxy%40123@$IP:$PORT
#npm config set proxy $http_proxy
#npm config set https-proxy $http_proxy
有时会突然下载不了,需要服务器端重启
安装你的私有包¶
如果你上传了一个私有包到你的私有索引(例如你创建的 :root/dev),则将 URL 改为:
pip install your-private-package --index-url http://<Server_IP>:3141/root/dev/ --trusted-host <Server_IP>
加速效果对比¶
第一次下载
> pip install vllm-ascend==0.11.0rc0 -i http://80.253.12.220:3141/root/pypi --trusted-host 80.253.12.220
Collecting torch>=2.7.1 (from vllm-ascend==0.11.0rc0)
Downloading http://80.253.12.220:3141/root/pypi/%2Bf/1cc/208435f6c379f/torch-2.9.1-cp310-cp310-manylinux_2_28_aarch64.whl (104.2 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 104.2/104.2 MB 1.5 MB/s eta 0:00:00
第二次下载
> pip install vllm-ascend==0.11.0rc0 -i http://80.253.12.220:3141/root/pypi --trusted-host 80.253.12.220
Collecting torch>=2.7.1 (from vllm-ascend==0.11.0rc0)
Downloading http://80.253.12.220:3141/root/pypi/%2Bf/1cc/208435f6c379f/torch-2.9.1-cp310-cp310-manylinux_2_28_aarch64.whl (104.2 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 104.2/104.2 MB 36.2 MB/s 0:00:02
缓存位置在C:\Users\t00906153\.devpi\server\+files\root\pypi\+f下
pypiserver¶
Pypiserver 是一个非常轻量级的 Python 包仓库服务器,它的核心目标是提供一个简单、快速的方式来搭建私有的 PyPI 兼容索引。
- 无缓存: pypiserver 只是充当一个转发机制,它不会将上游下载的包文件存储(缓存)到你的本地目录。每次请求一个本地没有的包时,它都会再次回源到上游。
- 快速测试、原型搭建或小型团队。
- 只需要发布和分发少量私有包。
- 不要求高性能或复杂的上游缓存功能。
部署和使用¶
1. 安装 \(\text{pypiserver}\)¶
首先,在一台稳定运行的机器(可以是你的本地机器,也可以是局域网内的服务器)上安装它:
2. 启动服务器¶
选择一个目录作为软件包的存储位置,然后启动服务器。例如,使用 \(\text{pypiserver}\) 的缓存模式并指定上游 \(\text{pypi}\) 源:
# 假设你想把缓存的包放在 /path/to/my/packages 目录下
> pypi-server run /home/t00906153/cache_pip --fallback-url https://pypi.org/simple/ --passwords .htpasswd │
/home/t00906153/cache_pip: 指定本地包的存储路径。--fallback-url https://pypi.org/simple/: 启用缓存模式 (\(\text{proxy}\) 模式),它会在本地找不到包时,向上游 \(\text{pypi}\) 源请求。--passwords .htpasswd: 可选,用于设置上传(如果你也想用它来托管私有包)的认证。
服务器默认运行在 http://localhost:8080 (如果你是在服务器上运行,将 \(\text{localhost}\) 替换为服务器的 \(\text{IP}\) 地址)。
报错:apache.passlib library is not available. You must install pypiserver with the optional 'passlib' dependency (pip install pypiserver['passlib']) in order to use password authentication
安装密码所需包pip install pypiserver['passlib'] , zsh要打双引号。
搭建成功
(base) root@node-94-158 ~ [11:43:40]
> pypi-server run /home/t00906153/cache_pip --fallback-url https://mirrors.aliyun.com/pypi/simple/ -v --backend cached-dir
Bottle v0.12.25 server starting up (using AutoServer())...
Listening on http://0.0.0.0:8080/
Hit Ctrl-C to quit.
<LocalRequest: GET http://127.0.0.1:8080/simple/torch-npu/>
200 OK
<LocalRequest: GET http://127.0.0.1:8080/simple/pip/>
200 OK
<LocalRequest: GET http://127.0.0.1:8080/>
200 OK
验证网络联通,注意不要被代理了
> curl -v http://127.0.0.1:8080
* Uses proxy env variable no_proxy == '127.0.0.1,localhost,local,.local'
* Trying 127.0.0.1:8080...
* Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> Host: 127.0.0.1:8080
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: TwistedWeb/23.10.0
< Date: Tue, 09 Dec 2025 07:58:35 GMT
< Content-Length: 1007
< Content-Type: text/html; charset=UTF-8
<
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Welcome to pypiserver!</title>
</head>
<body>
<h1>
Welcome to pypiserver!
3. 配置 \(\text{pip}\) 使用本地缓存¶
在你的 \(\text{Conda}\) 环境构建过程中,你需要告诉 \(\text{pip}\) 使用你刚刚搭建的本地服务器作为安装源。
在你运行 \(\text{pip install}\) 命令时,通过 -i 或 --index-url 参数指定本地源:
# pip install -i http://<服务器IP或域名>:8080/simple --trusted-host <服务器IP或域名> <包名>
# 本地搭建
pip install vllm-ascend==0.11.0rc0 -i http://127.0.0.1:8080/simple --trusted-host 127.0.0.1
# win搭建,80.253.12.220为win代理网卡 ip
# 先 unset http_proxy,或者 export no_proxy=127.0.0.1,localhost,local,.local,$IP
# 测试curl -v http://80.253.12.220:8080
pip install vllm-ascend==0.11.0rc0 -i http://80.253.12.220:8080/simple --trusted-host 80.253.12.220 --trusted-host mirrors.aliyun.com
提示:
--trusted-host是必要的,因为 \(\text{pypiserver}\) 默认使用 \(\text{HTTP}\) 而非安全的 \(\text{HTTPS}\)。- 首次安装:包会被从 \(\text{pypi.org}\) 下载并缓存到你指定的
/path/to/my/packages目录。 - 后续安装:相同的包和版本将直接从你的本地磁盘提供,速度会非常快。
/home/t00906153/cache_pip 是空的
并不会缓存到这里
跨机器使用推荐win作为中央服务器
内网封锁严格,机器分布在多个地域网段, 不如win作为中间机器
pypiserver 并不会缓存上游包
其余方案¶
另一个 \(\text{Conda}\) 专用的解决方案:\(\text{Artifactory}\) 或 \(\text{Nexus}\)
如果你的主要需求是加速整个 \(\text{Conda}\) 环境的构建,并不仅仅是 \(\text{pip}\) 包,那么企业级的通用二进制仓库管理器(如 \(\text{JFrog Artifactory}\) 或 \(\text{Sonatype Nexus}\))会更合适。
- 功能: 它们不仅可以作为 \(\text{pypi}\) 的代理缓存,还可以作为 \(\text{Conda}\) 源(\(\text{conda}\) channel)的代理缓存,并且支持 \(\text{Docker}\) 镜像、\(\text{Maven}\) 等几乎所有类型的包管理系统。
- 优点: 一次配置,可以加速 \(\text{conda install}\) 和 \(\text{pip install}\)。
- 缺点: 相比 \(\text{pypiserver}\) 更加复杂,部署和维护成本更高。
如果你的团队或公司已经在使用这些工具,请直接配置它们作为 \(\text{pypi}\) 和 \(\text{conda}\) 的代理。