Pip Cache

导言

VeRL场景开发时,安装包特别多和复杂:

  1. CANN
  2. torch\torch_npu
  3. vllm\vllm_ascend
  4. MindSpeed\megatron
  5. transformer

开发时还要pip install -e . 还要修改代码。

传统的思路是docker镜像或者conda打大包,但是这种包一个就是20GB+,但是这是商发时的策略,开发时即使只是修改一行,但是还是要重新出一个20GB大包。

思路是借助并加速pip的原子化构建:

  • 在内网服务器上建立一个pip包缓存站,
  • 不仅能缓存官方包,
  • 自己修改的代码包也能提交。
  • 最终实现,除了CANN安装,其余pip包,一行pip intall -r requirements.txt就行。

DevPI

DevPI 不仅仅是一个私有索引,它是一个功能完备的 PyPI 仓库和分发系统。

核心优势

  1. 缓存代理 (Caching Proxy): 这是你最关心的功能。DevPI 默认配置了一个名为 :root/pypi 的上游索引,它会自动从官方 PyPI 下载包并将其缓存在本地。这样,第二次请求同一个包时,DevPI 会直接从本地提供,大大加快速度并支持离线安装。
  2. 多索引管理 (Multi-Index Management): DevPI 允许创建多个虚拟索引(Index)。你可以基于上游 PyPI 创建自己的私有索引(例如 :root/dev),也可以将这些索引链接起来,实现开发、测试、生产环境的包隔离。
  3. 上传私有包 (Private Packages): 你可以使用 devpi upload 命令将自己的私有包上传到特定的索引中。
  4. 易于部署: 虽然功能强大,但 DevPI 基于 Python,安装和初始化非常便捷。

DevPI 服务端搭建

1. 安装 DevPI 及其依赖

在 Windows 的命令行或 PowerShell 中执行安装命令:

1
2
3
4
# -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 需要一个本地目录来存放数据和缓存。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 切换到一个你希望存储 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 服务器

1
2
#  0.0.0.0 来监听所有
devpi-server --serverdir D:\DevPI_Data --host 0.0.0.0

curl 验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
(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 工具可以方便地管理索引和登录,推荐在客户端安装。

步骤一:安装客户端
1
pip install devpi-client
步骤二:指定服务器地址

使用 devpi use 命令来告诉客户端 DevPI 服务器的地址:

1
2
3
4
5
6
7
8
9
10
# 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修改密码:
1
2
3
4
5
6
7
(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 下载的包。你不需要额外配置。
步骤四:换源
1
2
3
4
5
6
7
8
9
10
# 清华源 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 索引:

1
2
# 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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 改为:

1
pip install your-private-package --index-url http://<Server_IP>:3141/root/dev/ --trusted-host <Server_IP>

加速效果对比

第一次下载

1
2
3
4
5
6
> 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

第二次下载

1
2
3
4
5
> 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}$

首先,在一台稳定运行的机器(可以是你的本地机器,也可以是局域网内的服务器)上安装它:

1
pip install pypiserver

2. 启动服务器

选择一个目录作为软件包的存储位置,然后启动服务器。例如,使用 $\text{pypiserver}$ 的缓存模式并指定上游 $\text{pypi}$ 源:

1
2
# 假设你想把缓存的包放在 /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要打双引号。

搭建成功

1
2
3
4
5
6
7
8
9
10
11
12
13
14
(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

验证网络联通,注意不要被代理了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
> 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 参数指定本地源:

1
2
3
4
5
6
7
# 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作为中间机器

1
2
3
4
5
(tsj_debug_pypi-server) root@localhost ~  [11:29:49]
> nc -zv 80.5.5.74 8080
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Connected to 80.5.5.74:8080.
Ncat: 0 bytes sent, 0 bytes received in 0.01 seconds.

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}$ 的代理。

参考文献

Author

Shaojie Tan

Posted on

2025-12-09

Updated on

2025-12-13

Licensed under