uv还是pip:冷缓存快6.4倍,私有索引才是迁移门槛

|作者: QUASA 编辑团队|2 分钟阅读
uv还是pip:冷缓存快6.4倍,私有索引才是迁移门槛

现有 Python 项目可以先保留 requirements.txt,用 uv 替换依赖安装命令,再决定是否迁移整个项目工作流。一项在 Mac mini M4 Pro 上完成的禁缓存八包测试以五次运行的中位数计,uv 安装耗时 0.381 秒,pip 为 2.457 秒,约快 6.4 倍。这是特定机器、依赖和工具版本下的安装结果,不能直接换算成现有 CI 的提速幅度。

能否切换,首先取决于依赖是否仍从预期位置安装。uv 的 pip 兼容说明指出,uv 面向常见 pip 工作流,但不会读取 pip.conf、PIP_INDEX_URL 等 pip 专用配置。项目若使用私有包,应先为 uv 配好索引和凭据,再核对包的来源、版本与构建结果;仅把命令中的 pip 改成 uv 不足以完成这一步。

6.4 倍测到的是哪段时间

Mac mini M4 Pro 上相同八包的禁缓存安装对比:uv 为 0.381 秒,pip 为 2.457 秒。

这组比较只计算依赖安装,没有把创建虚拟环境的时间算进去。两边使用同一份包含八个直接依赖的文件,并关闭各自缓存,因此适合说明该条件下的冷安装差距。它不代表热缓存安装,也不代表包含环境创建、测试和构建的整条流水线。若 CI 大部分时间花在运行测试或编译项目上,依赖安装即使明显变快,整项任务缩短的时间仍可能有限。

比较现有项目时,应固定 Python 版本、操作系统、依赖文件和索引条件,分别记录安装耗时与完整 CI 耗时。冷缓存测试要让双方都不使用已有下载与构建缓存;热缓存测试则让双方各自预热,再安装到新环境。每轮还要记录实际取得的是预编译 wheel 还是源码包,否则一次额外的编译就可能盖过安装器本身的差别。

另一份公开基准的问题记录显示,uv 的冷安装结果曾从约 3 秒升至约 20 秒;排查发现,当时 uv 与对照的 Poetry 解析到了不同版本的 python-rapidjson,其中一侧需要从源码构建。该案例比较的是另一套依赖和命令,不能用来推翻八包测试,也说明速度排名只有在解析结果和构建方式可比时才有意义。

私有索引改变的不只是下载地址

内部索引与 PyPI 存在同名包时,uv 依配置的首个索引选择候选版本;pip.conf 设置不会自动继承。

pip 能从内部仓库安装成功,可能依赖本机 pip.conf 或 CI 注入的 PIP_INDEX_URL。uv 不会继承这些设置,迁移时须显式提供它自己的索引配置,并在实际流水线中提供凭据。验收不能只看命令是否返回成功:还应核对内部包的来源、选中的版本,以及同名包是否可能从公开索引取得。

uv 的索引文档说明,默认策略会在首个找到某包的索引停止搜索,只从该索引选择候选版本;pip 会合并多个索引的候选版本。因此,即使两边都配置了内部索引和 PyPI,同名包仍可能得到不同的解析结果。这个默认策略有助于避免公开索引上的同名包取代内部包,但切换工具时需要确认它是否符合项目原有的版本选择规则。

uv 可以在项目配置中定义索引,也可以为指定依赖绑定特定索引。若仅试用 uv pip 接口,索引还可以通过相应的命令参数或 uv 环境变量提供;写在项目配置的索引设置则便于团队核对。凭据应按索引的认证方式注入 CI,不宜因为本地开发机已有登录状态就推定自动化任务也能访问。对于会把未认证请求转到公开仓库的私有索引,还要确认认证请求确实发生,否则“安装成功”也可能掩盖错误的包来源。

沿用 requirements.txt 的分阶段迁移

第一阶段只更换安装器:保留原有依赖文件,在独立虚拟环境中运行 uv pip install -r requirements.txt,再执行项目现有测试。这样能把安装行为的差异与依赖声明格式的变更分开。若文件只约束顶层依赖,两个工具仍可能解析出不同的传递依赖;需要比较完整的已安装版本和发行文件,而不能只检查文件中的包名。

  1. 用同一份 requirements.txt、同一 Python 版本和平台建立 pip 与 uv 两组新环境。记录工具版本、索引设置、解析结果,以及项目测试是否通过。
  2. 分别测冷缓存和热缓存安装,再测完整 CI 任务。把下载、源码构建或网络波动造成的变化与安装器的耗时区别开。
  3. 接入私有索引及 CI 凭据,核对内部包和同名包的实际来源。覆盖生产流水线使用的镜像、代理与认证方式。
  4. 补测本地可编辑包、路径依赖和必须从源码构建的包。通过后再逐步切换 CI 任务,同时保留原安装命令以便定位差异。

进一步改用 pyproject.toml 和 uv.lock 是另一阶段的决定。官方迁移指南提供了从 requirements 文件导入项目依赖的方法,也说明可将现有固定版本作为约束,避免导入时顺带升级。原文件若按平台分别锁定依赖,还需处理环境标记;直接把多个平台的固定版本一并作为约束,可能造成冲突。先完成安装器切换,再考虑锁定方式,测试失败时更容易找到变化来源。

可编辑安装和源码构建如何验收

使用可编辑安装的项目,应把本地包纳入迁移测试。安装后检查 Python 导入的是否为预期源码路径,并确认修改源码后相关测试仍表现正常。可编辑模式依赖构建后端的支持;含原生扩展的包即使以可编辑方式安装,修改扩展代码后也可能仍需重新编译。只测试公开索引上的普通 wheel,无法覆盖这些开发环境行为。

源码包要同时检查构建声明和环境。uv 默认采用隔离构建,旧包若依靠环境中预先存在、却未声明的构建依赖,就可能在新环境失败。应先查看该依赖是否已有修正构建声明的版本,并核对 CI 的 Python、系统库和编译工具。一个平台取得预编译 wheel,另一个平台却可能必须编译同一个依赖;两边的安装时间和失败原因因此不能直接类比。

是否继续推进迁移,应由项目的安装结果和整条流水线收益共同决定。公开索引中的常规 wheel、稳定的版本约束和通过的项目测试,会让替换安装命令相对简单;内部索引、认证或特殊构建尚未通过验收时,生产任务应先沿用已验证的 pip 路径。待这些具体差异解决后,再评估 uv.lock 是否能为团队提供所需的跨环境版本锁定,而无需让一次冷安装成绩代替工作流决策。

相关阅读:

分享:

订阅我们的新闻通讯

将最新 Web3、AI 和加密货币新闻直接发送到您的邮箱。

0