uv pip 接口实战指南:作为 pip、pip-tools 与 virtualenv 替代命令的完整工作流
本文系统讲解 uv 的 uv pip 接口——一套可直接替代 pip、pip-tools 和 virtualenv 常见命令的低级包管理接口。读完你可以掌握:如何创建与定位 Python 虚拟环境、如何安装/卸载/检查包、如何用 pyproject.toml 或 requirements.in 声明依赖,以及如何通过 uv pip compile 锁定版本、用 uv pip sync 精确同步环境,并理解 uv 与 pip 行为上的关键差异及其源码实现位置。
定位:一个面向高级用户的低级包管理接口
uv 的 uv pip 子命令组被设计为 pip、pip-tools 和 virtualenv 常用命令的"即插即用"替代(drop-in replacement)。它与 uv 的主力接口(如 uv add、uv run、uv lock 等项目级命令)的核心区别在于:项目级接口会自动为你管理虚拟环境,而 uv pip 命令则直接操作你手头的虚拟环境。这种定位把 uv 的速度与能力暴露给两类用户:
- 已经熟悉
pip/pip-tools工作流、希望无缝切换的高级用户; - 尚未准备好完全迁移到 uv 项目接口的存量项目。
有两点前提需要先明确(见 The pip interface):
- uv 并不依赖 pip,更不会调用 pip。 之所以保留
pip这个名字,是为了强调这是一组与 pip 接口对齐的低级命令,并将其与更高层抽象的项目命令区分开。你可以用uv替代pip install,但 uv 内部实现完全是独立的 Rust 代码(核心实现在 crates/uv/src/commands/pip 目录中)。 - 这些命令并不是 pip 工具的逐字复刻。 你越偏离常见工作流,越可能遇到行为差异。官方在 兼容指南 中列出了所有已知差异,本文末尾也会汇总要点。
从源码结构看,uv pip 的子命令在 uv-cli 的 PipCommand 枚举 中定义,共九个公开子命令:compile、sync、install、uninstall、freeze、list(别名 ls)、show、tree、check,以及一个隐藏的实验性 debug。每个子命令都有对应的独立实现文件(如 install.rs、sync.rs、compile.rs),与本文下面各节一一对应。
创建与使用 Python 虚拟环境
每个 Python 安装都带有一个"活动环境",安装包到该环境后模块才可被脚本导入。最佳实践是不直接修改 Python 安装自带的环境——尤其是操作系统自带的 Python,因为发行版往往自己管理这些包。虚拟环境(virtual environment)正是把包与解释器环境隔离开来的轻量方案。与 pip 不同,uv 默认强制使用虚拟环境。
创建虚拟环境
等价于 virtualenv 的 uv venv 命令:
$ uv venv # 在 ./.venv 创建虚拟环境
$ uv venv my-name # 指定名称或路径
$ uv venv --python 3.11 # 请求特定 Python 版本
--python 3.11 这样的版本请求要求系统上存在对应版本;若不存在,uv 会直接为你下载所需的 Python 解释器(详见 Python 版本管理)。
创建完成后,如果使用默认的 .venv 名称,uv 在后续调用中会自动发现并使用它:
$ uv venv
$ # 在新虚拟环境中安装包
$ uv pip install ruff
激活环境
虚拟环境可以"激活",使其中的包对当前 shell 可见:
=== "macOS 和 Linux"
```console
$ source .venv/bin/activate
```
=== "Windows"
```pwsh-session
PS> .venv\Scripts\activate
```
默认的 Unix 激活脚本面向 POSIX 兼容 shell(sh、bash、zsh)。仓库中为常见替代 shell 都提供了对应脚本(对应 uv-virtualenv crate 内嵌的激活脚本模板):
- fish:
$ source .venv/bin/activate.fish - csh / tcsh:
$ source .venv/bin/activate.csh - Nushell:
$ use .venv\Scripts\activate.nu
退出虚拟环境则使用 deactivate:
$ deactivate
使用任意 Python 环境
uv 本身不依赖 Python 运行,因此它完全可以操作"别的 Python"的环境,这是 uv pip 接口非常实用的一个特性:
VIRTUAL_ENV环境变量:设置VIRTUAL_ENV=/path/to/venv后,uv 会直接向/path/to/venv安装,与 uv 自身安装在哪里无关。注意:如果该目录不是符合 PEP 405 规范的虚拟环境,该变量会被忽略。--python选项:可以安装到任意环境,甚至是非虚拟环境。uv pip install --python /path/to/python会安装到该解释器关联的环境中;--python也接受虚拟环境根目录的路径。--system选项:uv pip install --system安装到系统 Python 环境,大致等价于uv pip install --python $(which python)(但会跳过链接到虚拟环境的可执行文件)。虽然官方仍推荐虚拟环境,但--system适用于 CI 和容器场景。
--system 标志还有一个语义:它是"允许修改系统(非虚拟)环境"的显式开关。例如你用 --python 3.12 请求一个 Python 版本时,uv 会搜索满足请求的解释器;若找到的是系统解释器(如 /usr/lib/python3.12),必须同时提供 --system 才允许修改它,否则 uv 会忽略所有非虚拟环境的解释器。反过来,提供了 --system 时,uv 会忽略所有虚拟环境内的解释器。
官方也坦承:跨平台、跨发行版向系统 Python 安装包 notoriously 困难,uv 支持常见情况但不保证覆盖所有场景——例如 Python 3.10 之前的 Debian 系统 Python 因发行版补丁了 distutils(却没有同步补丁 sysconfig)而不被支持。在这些非标准环境中,虚拟环境是硬性要求。
另外注意:如果 uv 本身是通过 pip 安装在某个 Python 环境里的,它依然可以修改其他环境;但用 python -m uv 方式调用时,uv 会默认使用父解释器所在的环境。通过 Python 调用 uv 会增加启动开销,不推荐日常使用。uv 自身不依赖 Python,但它在(1)向环境安装依赖和(2)构建源分发包(sdist)这两个环节需要定位到一个 Python 环境。
环境发现顺序
执行 uv pip sync、uv pip install 这类会修改环境的命令时,uv 按以下顺序搜索虚拟环境(见 environments 文档):
- 由
VIRTUAL_ENV环境变量标识的已激活虚拟环境; - 由
CONDA_PREFIX标识的已激活 Conda 环境; - 当前目录或最近的父目录中的
.venv(即使未激活)。
如果三者都找不到,uv 会提示你在当前目录用 uv venv 创建一个。带 --system 标志时跳过虚拟环境搜索;对于不修改环境的命令(如 uv pip compile),uv 不要求虚拟环境存在,但仍需要一个 Python 解释器(发现机制见 Python 版本发现)。
安装与管理包
安装:从包名、版本到 Git 仓库
基础安装:
$ uv pip install flask # 按名称安装
$ uv pip install "flask[dotenv]" # 启用可选依赖 extra
$ uv pip install flask ruff # 一次安装多个
$ uv pip install 'ruff>=0.2.0' # 带版本约束
$ uv pip install 'ruff==0.3.0' # 固定版本
非注册表来源同样支持,且写法与 pip 一致:
$ uv pip install "ruff @ ./projects/ruff" # 本地目录
$ uv pip install "git+https://github.com/astral-sh/ruff" # Git 仓库
Git 依赖可以精确到 tag、commit 或分支:
$ uv pip install "git+https://github.com/astral-sh/ruff@v0.2.0" # tag
$ uv pip install "git+https://github.com/astral-sh/ruff@1fadefa67b26508cc59cf38e6130bde2243c929d" # commit
$ uv pip install "git+https://github.com/astral-sh/ruff@main" # 分支
私有仓库的认证方式见 Git 认证文档。
可编辑(editable)安装
可编辑包在源码修改后无需重新安装即可生效:
$ uv pip install -e . # 安装当前项目为可编辑包
$ uv pip install -e "ruff @ ./project/ruff" # 安装其他目录的项目
从文件批量安装
uv pip install 支持从标准文件格式批量安装:
$ uv pip install -r requirements.txt # requirements.txt
$ uv pip install -r pyproject.toml # pyproject.toml
$ uv pip install -r pyproject.toml --extra foo # 启用 "foo" extra
$ uv pip install -r pyproject.toml --all-extras # 启用全部 extra
依赖组(dependency groups)也可以直接安装:
$ uv pip install --group foo # 当前目录 pyproject.toml 中的组
$ uv pip install --project some/path/ --group foo --group bar # 指定项目目录
$ uv pip install --group some/path/pyproject.toml:foo --group other/pyproject.toml:bar
与 pip 语义一致的一个注意点:--group 标志不会作用于 -r / -e 指定的其他来源。例如 uv pip install -r some/path/pyproject.toml --group foo 中的 foo 取自 ./pyproject.toml,而不是 some/path/pyproject.toml。
卸载
$ uv pip uninstall flask # 卸载单个包
$ uv pip uninstall flask ruff # 一次卸载多个
检查环境与包
环境检查对应 inspection 文档,共四类命令:
列出已安装包:
$ uv pip list # 表格形式列出全部包
$ uv pip list --format json # JSON 输出,便于脚本处理
$ uv pip freeze # 以 requirements.txt 格式列出
查看包详情:
$ uv pip show numpy # 支持同时传入多个包
校验环境一致性。分多次安装可能装入互相冲突的依赖,用 uv pip check 检查冲突与缺失依赖:
$ uv pip check
从 兼容指南 可以看到 uv pip check 当前会报告五类诊断:包缺少 METADATA 文件或无法解析、Requires-Python 与当前解释器不匹配、依赖缺失、依赖版本不兼容、同一包在环境中存在多个版本。其中"同包多版本"是 pip check 不会报而 uv 会报的。
uv pip tree 还可以以树状图展示环境内的依赖关系(见 PipCommand 定义),适合排查复杂依赖链。
声明依赖
最佳实践是把依赖声明在静态文件里,而不是对环境做即兴安装;声明之后即可用 uv pip compile 锁定,得到一致、可复现的环境(见 declaring dependencies)。
使用 pyproject.toml
pyproject.toml 是 Python 项目定义依赖的标准载体:
[project]
dependencies = [
"httpx",
"ruff>=0.3.0"
]
可选依赖(extras):
[project.optional-dependencies]
cli = [
"rich",
"click",
]
每个 key 定义一个 extra,可通过 --extra / --all-extras 标志或 package[<extra>] 语法安装。
使用 requirements.in
轻量级的 requirements 文件格式也是常用声明方式,每个需求占一行。习惯上命名为 requirements.in,与锁定产物 requirements.txt 区分:
httpx
ruff>=0.3.0
注意该格式不支持可选依赖组。
锁定与同步环境
锁定的含义是:把 ruff 这样的依赖解析为一个精确版本写入文件,使环境可复现。不锁定的话,依赖版本会随时间、工具或平台变化。
锁定 requirements
uv pip compile 支持多种输入格式(见 locking environments):
$ uv pip compile pyproject.toml -o requirements.txt # 标准输入来源
$ uv pip compile requirements.in -o requirements.txt
$ uv pip compile pyproject.toml requirements-dev.in -o requirements-dev.txt # 多文件
$ uv pip compile setup.py -o requirements.txt # 兼容遗留 setup.py / setup.cfg
$ echo "ruff" | uv pip compile - # 从 stdin 读取(用 -)
注意:默认情况下 uv pip compile 的输出只是打印到终端,必须用 --output-file / -o 才写入文件——这是与 pip-tools 的默认行为差异之一。
extras 与依赖组:
$ uv pip compile pyproject.toml --extra foo # 启用 "foo" extra
$ uv pip compile pyproject.toml --all-extras # 全部 extra
$ uv pip compile --group foo # 锁定当前目录的依赖组
$ uv pip compile --project some/path/ --group foo --group bar
$ uv pip compile --group some/path/pyproject.toml:foo --group other/pyproject.toml:bar
requirements.in 格式不支持 extras;--group 是 pip-tools 尚未实现的扩展(uv 先行支持)。--group 同样只作用于默认项目目录,不作用于其他显式指定的来源文件。
升级已锁定的依赖
使用输出文件时,uv 会尊重输出文件中已钉住的版本——已钉住的依赖在后续 compile 中不会被升级:
$ echo "ruff==0.3.0" > requirements.txt
$ echo "ruff" | uv pip compile - -o requirements.txt
# 结果仍是 ruff==0.3.0
需要升级时用:
$ uv pip compile - -o requirements.txt --upgrade-package ruff # 升级单个包
$ uv pip compile - -o requirements.txt --upgrade # 升级全部
同步环境:uv pip install 与 uv pip sync 的区别
依赖可以直接从定义文件或编译出的 requirements.txt 用 uv pip install 安装。但要理解一个关键区别:uv pip install 不会移除环境中已有的、锁文件里没有声明的包(除非它们与锁文件冲突),这对可复现性并不理想。若要保证环境与锁文件严格一致,应使用 uv pip sync——它会把锁文件中未列出的包从环境中移除:
$ uv pip sync requirements.txt # 与 requirements.txt 精确同步
$ uv pip sync pylock.toml # 也支持 PEP 751 的 pylock.toml
从 CLI 的源码注释也能印证这一语义:Sync 子命令的帮助文本 明确写着"同步时会移除文件中未列出的包;想保留多余包请改用 uv pip install",并支持 --strict 在文件中缺少传递依赖时给出警告。
约束文件(constraints)
约束文件是 requirements.txt 风格文件,但只控制需求的版本,不会触发安装。典型用途:给"不是本项目直接依赖"的包加上版本边界:
pydantic<2.0
$ uv pip compile requirements.in --constraint constraints.txt
支持每文件多条约束、多个约束文件。uv 还会读取工作区根 pyproject.toml 中的 constraint-dependencies 字段并追加到命令行指定的约束之上。
构建约束(build constraints)
与 constraints 类似,但专门针对构建期依赖(包括构建运行时依赖所需的构建依赖)。把包写进构建约束文件不会让它被安装;约束只在该包作为直接或传递的构建期依赖出现时生效。例如统一工作区内所有包使用的 setuptools 版本:
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
setuptools==75.0.0
uv 同样会读取工作区根 pyproject.toml 的 build-constraint-dependencies 并追加进去。
覆盖(overrides)
overrides 与 constraints 的本质区别:constraints 是加法的(与各包声明的需求求交集),overrides 是绝对的(完全替换各包声明的需求,即使这会产生"非法"的解)。最常见用途是移除传递依赖的上界。例如 a 要求 c>=1.0,<2.0、b 要求 c>=2.0,二者不可兼得;用 override 强制 c>=2.0 后即可解析成功(但注意若 a 确实不兼容 c>=2.0,运行时会出问题):
c>=2.0
$ uv pip compile requirements.in --override overrides.txt
支持每文件多条 override、多个 override 文件。
与 pip 的关键行为差异
以下要点摘自 兼容指南,是切换前必须了解的差异:
- 不读 pip 的配置与变量。uv 不读
pip.conf、不读PIP_INDEX_URL等 pip 专属配置,取而代之的是自己的UV_INDEX_URL等环境变量以及uv.toml/pyproject.toml的[tool.uv.pip]段。 - 虚拟环境是默认值。
uv pip install/uv pip sync总是安装到已激活虚拟环境或搜索到的.venv;pip 则相反,无活动环境时装到全局。uv 要求显式--python或--system才能碰非虚拟环境——默认值被刻意反转。 - 多索引策略更安全。uv 默认采用
first-index策略:按顺序搜索索引,在第一个包含该包的索引处停止,候选版本只取该索引的,以此防范 dependency confusion 攻击(pip 会合并所有索引的候选版本)。可用--index-strategy/UV_INDEX_STRATEGY切换unsafe-first-match或unsafe-best-match(后者最接近 pip,但有安全风险)。 - PEP 517 构建隔离默认开启。包因构建依赖缺失而装不上时,可先预装构建依赖再用
--no-build-isolation:uv pip install wheel && uv pip install --no-build-isolation biopython==1.77。 pip check、--user、--only-binary等存在语义差异。uv 不支持--user(推荐虚拟环境);--only-binary在 uv 中对直接 URL 依赖也强制(pip 不强制),但 editable 安装两者都放行。- 默认不编译字节码。pip 安装时会生成
__pycache__,uv 默认不生成,可用--compile-bytecode或UV_COMPILE_BYTECODE=1开启(例如 Docker 构建中建议开启以提升启动速度)。 pip compile默认差异。uv 默认不写输出文件(必须-o)、默认剥离 extras(--strip-extras,与 pip-tools 即将变更的默认值对齐)、默认不在输出中写索引 URL(用--emit-index-url开启)。- 预发布版本策略。默认
if-necessary:优先稳定版,仅当所有满足约束的稳定候选都被拒绝时才回退到预发布;--prerelease allow/disallow/explicit可切换策略。 - 更严格、更规范。uv 往往比 pip 严格——拒绝文件名与元数据不一致的 wheel(可用
UV_SKIP_WHEEL_FILENAME_CHECK=1放宽)、拒绝非法 URL fragment 的 HTML 索引等;包名默认按 PEP 503 归一化输出(docstring-parser而非docstring_parser)。
源码结构速览
想在源码层面继续深入时,入口非常清晰:
- 子命令声明:crates/uv-cli/src/lib.rs 中的
PipCommand,可对照本文各节查看每个子命令的完整帮助文本; - 命令实现:crates/uv/src/commands/pip 下的 install.rs、sync.rs、compile.rs、uninstall.rs、freeze.rs、list.rs、show.rs、tree.rs、check.rs 与共享操作层 operations.rs;
- 其中 mod.rs 里的
resolution_markers/resolution_tags展示了uv pip命令如何根据--python-version/--python-platform计算解析用的 marker 环境与 wheel 标签——这正是uv pip compile能跨平台锁定的底层机制之一; - 完整的端到端测试在 crates/uv/tests/pip_compile 与 crates/uv/tests/pip_install 等目录中,可用
cargo test运行验证。
小结
uv pip 是 uv 中面向存量 pip/pip-tools 工作流的"直译层":命令名、参数习惯与 pip 高度对齐,但默认行为更安全(强制虚拟环境、first-index 索引策略、PEP 517 隔离构建)。日常工作流可以概括为三步——uv venv 建环境、uv pip compile 锁版本、uv pip sync 精确同步环境;临时探索则直接用 uv pip install / uv pip uninstall,并用 uv pip check 兜底校验环境一致性。只要记住"它不依赖 pip、也不是 pip 的逐字复刻",绝大多数 pip install 替换成 uv pip install 即可直接工作。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00