Python 包管理:uv
Python 项目管理长期以来依赖一组分散工具:pip 负责安装包,venv 或 virtualenv 负责虚拟环境,pip-tools 负责锁定依赖,pipx 负责安装命令行工具,pyenv 负责管理 Python 版本,poetry 或 pdm 负责项目级依赖管理。
uv 把这些功能尽量收敛到一个命令行工具里。它由 Astral 开发,使用 Rust 编写,定位是一个高速的 Python 包与项目管理器。
实际使用中,uv 最值得关注的不是“快”本身,而是它把 Python 开发中最常见的几个动作统一成了一套一致的工作流:创建项目、声明依赖、生成锁文件、同步虚拟环境、运行脚本、安装 Python 解释器、管理全局 CLI 工具,以及构建和发布包。
uv 的两种工作模式
第一种是项目管理模式。这是更推荐的现代工作流。项目依赖写在 pyproject.toml 中,解析结果写入 uv.lock,本地环境通常是项目目录下的 .venv。开发者通过 uv add、uv remove、uv lock、uv sync 和 uv run 来管理项目。
第二种是pip 兼容模式。它更像传统的 pip、pip-tools、virtualenv 工作流。开发者可以继续使用 requirements.txt,并用 uv pip install、uv pip compile、uv pip sync 等命令替代原来的工具链。
如果是新项目,优先使用项目管理模式。如果是老项目、CI 脚本或已有 requirements.txt 的项目,可以先从 pip 兼容模式迁移。
安装 uv
macOS 和 Linux 可以使用官方安装脚本:
1
curl -LsSf https://astral.sh/uv/install.sh | sh
Windows PowerShell:
1
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
也可以通过包管理器安装:
1
2
3
brew install uv
pipx install uv
pip install uv
安装后检查版本:
1
uv --version
如果你是通过 standalone installer 安装的 uv,可以用下面的命令升级 uv 自身:
1
uv self update
缓存与目录管理
uv 的速度很大程度来自缓存机制。它会缓存下载过的包、构建过的 wheel、源码包以及工具运行所需的环境。理解这些目录的位置,有助于排查磁盘占用、配置 CI 缓存,以及区分“项目环境”和“全局工具环境”。
查看 uv 的缓存目录
查看当前缓存目录:
1
uv cache dir
默认情况下,缓存目录通常位于:
| 系统 | 默认缓存目录 |
|---|---|
| Linux | ~/.cache/uv 或 $XDG_CACHE_HOME/uv |
| macOS | ~/Library/Caches/uv |
| Windows | %LOCALAPPDATA%\uv\cache |
这个目录主要用于存放 uv 的包缓存,包括下载的 distributions、构建产物、源码包、wheel 等。也就是说,uv pip install、uv sync、uv add、uvx 等命令复用依赖时,都会受益于这个缓存。
需要注意,不建议手动删除缓存目录里的局部文件。官方建议使用 uv 自带命令管理缓存:
1
uv cache clean
如果只想清理某个包的缓存,可以使用:
1
uv cache clean requests
也可以删除当前未被使用的缓存项:
1
uv cache prune
修改缓存目录
临时指定某次命令使用的缓存目录:
1
uv pip install requests --cache-dir /path/to/uv-cache
长期修改缓存目录,建议设置环境变量:
1
export UV_CACHE_DIR=/path/to/uv-cache
Windows PowerShell 示例:
1
[Environment]::SetEnvironmentVariable("UV_CACHE_DIR", "D:\uv-cache", "User")
在 CI 中,也可以把 UV_CACHE_DIR 指向一个可缓存路径,例如:
1
export UV_CACHE_DIR="$HOME/.cache/uv"
然后让 CI 系统缓存这个目录,从而减少重复下载和构建时间。
uv 管理的 Python 版本目录
如果使用:
1
uv python install 3.12
uv 会下载并管理对应的 Python 解释器。查看 uv 管理的 Python 安装目录:
1
uv python dir
默认情况下,uv 管理的 Python 版本会放在持久数据目录的 python/ 子目录中。例如在 Linux 上通常类似:
1
~/.local/share/uv/python
查看 uv 管理的 Python 可执行文件目录:
1
uv python dir --bin
如果你希望修改 uv 管理 Python 的安装位置,可以使用环境变量:
1
export UV_PYTHON_INSTALL_DIR=/path/to/uv-python
uv tool install 的工具目录
uv tool install 用来安装全局可执行工具,例如:
1
uv tool install ruff
这些工具不会安装到某个项目的 .venv 中,而是安装到 uv 的工具目录里。查看工具安装目录:
1
uv tool dir
默认情况下,工具环境位于 uv 持久数据目录的 tools/ 子目录中。例如 Linux 上通常类似:
1
~/.local/share/uv/tools
查看工具可执行文件目录:
1
uv tool dir --bin
这个目录里会放置可直接调用的命令,例如 ruff、black、mypy 等。使用 standalone installer 安装 uv 时,uv 和 uvx 这两个可执行文件也会安装到对应的可执行文件目录中。
如果要修改工具环境目录,可以设置:
1
export UV_TOOL_DIR=/path/to/uv-tools
如果要修改工具可执行文件目录,可以设置:
1
export UV_TOOL_BIN_DIR=/path/to/bin
uvx 的临时工具环境
uvx 是 uv tool run 的简写:
1
uvx ruff check .
它会在隔离环境中运行命令行工具。与 uv tool install 不同,uvx 更偏向“临时执行”,适合偶尔运行某个工具,而不是把工具长期安装到系统路径中。
例如:
1
2
3
uvx pycowsay "hello uv"
uvx ruff check .
uvx black src/ --check
uvx 运行工具时会复用 uv 的缓存,因此第二次运行通常会更快。但它不会像 uv tool install ruff 那样,把 ruff 长期安装成一个稳定的全局命令。
新项目
创建一个新项目:
1
2
uv init my-app
cd my-app
uv init 会创建一个符合 pyproject.toml 规范的项目。某些文件和状态不一定会立即生成。例如,.venv 和 uv.lock 通常是在首次同步环境时才创建。
添加依赖:
1
uv add requests
这条命令会做几件事:
- 把
requests写入pyproject.toml; - 解析依赖版本;
- 更新
uv.lock; - 同步项目虚拟环境。
添加开发依赖:
1
uv add --dev pytest ruff
移除依赖:
1
uv remove requests
查看依赖树:
1
uv tree
手动生成或更新锁文件:
1
uv lock
同步本地环境:
1
uv sync
uv sync 的作用是让本地虚拟环境与 uv.lock 保持一致。默认情况下,它会移除 lockfile 中不存在的多余包。因此,它非常适合团队协作、CI 环境和生产部署前的环境对齐。
如果你希望保留环境里额外安装的包,可以使用:
1
uv sync --inexact
运行代码:优先使用 uv run
在项目里运行脚本:
1
uv run python main.py
或直接运行 Python 文件:
1
uv run main.py
uv run 会确保命令运行在合适的 Python 环境中。在项目目录中,它会先检查项目环境是否需要创建或更新,然后再执行命令。
这意味着你通常不需要手动执行:
1
source .venv/bin/activate
在日常开发中,可以直接使用:
1
2
3
uv run pytest
uv run ruff check .
uv run python scripts/report.py
需要注意的是,uv run 默认会确保所需依赖存在,但不会像 uv sync 那样默认删除环境中的多余包。如果你希望运行前也进行严格同步,可以使用:
1
uv run --exact python main.py
单文件脚本:用 PEP 723 声明内联依赖
uv 对单文件脚本也很友好。假设你有一个 script.py,文件头部声明了内联依赖:
1
2
3
4
5
6
7
8
9
# /// script
# dependencies = [
# "requests",
# ]
# ///
import requests
print(requests.get("https://example.com").status_code)
运行:
1
uv run script.py
uv 会读取脚本中的依赖元数据,并在隔离的临时环境中安装依赖后执行脚本。这个模式非常适合写一次性的自动化脚本、数据处理脚本或分享给同事的小工具。
也可以让 uv 帮你把依赖写入脚本元数据:
1
uv add --script script.py requests
管理 Python 版本
查看可用 Python 版本:
1
uv python list
安装指定 Python 版本:
1
uv python install 3.12
在当前项目中固定 Python 版本:
1
uv python pin 3.12
这会在项目中写入 .python-version,后续 uv 命令会优先使用这个版本。
如果你只是想为某个项目指定 Python 版本,可以这样做:
1
2
3
uv python install 3.12
uv python pin 3.12
uv sync
这能覆盖很多原本需要 pyenv 的场景。不过,如果你依赖复杂的 shell 集成、全局 Python shim 或系统级 Python 版本切换,仍然需要根据团队环境判断是否完全替换 pyenv。
管理命令行工具:替代 pipx
很多 Python 工具是命令行程序,例如 ruff、black、mypy、httpie。这些工具不一定应该安装进某个业务项目的 .venv 中。
临时运行一个工具:
1
uvx ruff check .
uvx 是 uv tool run 的简写,适合一次性运行工具。比如你没有提前安装 ruff,也可以直接执行。
指定工具版本:
1
2
uvx ruff@latest check .
uvx ruff@0.6.0 check .
长期安装一个全局工具:
1
uv tool install ruff
查看已安装工具:
1
uv tool list
升级工具:
1
uv tool upgrade ruff
卸载工具:
1
uv tool uninstall ruff
这个模式比把工具装进全局 Python 环境更干净,也避免污染具体项目的虚拟环境。
pip 兼容模式
如果你暂时不想迁移到 pyproject.toml,也可以继续使用 requirements.txt。
创建虚拟环境:
1
uv venv
指定 Python 版本创建虚拟环境:
1
uv venv --python 3.11
安装依赖:
1
uv pip install -r requirements.txt
安装单个包:
1
uv pip install requests
把宽松依赖锁定成 requirements.txt:
1
uv pip compile requirements.in -o requirements.txt
严格同步环境:
1
uv pip sync requirements.txt
这套命令适合旧项目、Dockerfile、CI 以及暂时不想引入 pyproject.toml 的仓库。
升级依赖
uv.lock 的目的不是“永远自动追最新”,而是保证可复现。也就是说,即使 PyPI 上发布了新版本,只要当前锁文件仍满足 pyproject.toml 中的版本约束,uv 不会自动升级锁定版本。
升级所有依赖:
1
2
uv lock --upgrade
uv sync
升级单个依赖:
1
2
uv lock --upgrade-package requests
uv sync
升级到指定版本:
1
2
uv lock --upgrade-package requests==2.32.3
uv sync
也可以直接在同步时升级:
1
uv sync --upgrade-package requests
如果你修改的是依赖约束本身,可以使用:
1
uv add "requests>=2.32"
这会更新 pyproject.toml 中的依赖声明。需要注意,锁定版本是否变化,取决于新约束是否排除了原来的锁定版本,或者你是否显式要求升级。
构建与发布 Python 包
如果你的项目是一个可发布的 Python 包,可以使用:
1
uv build
构建结果默认输出到 dist/ 目录,通常包括源码包和 wheel。
发布到包仓库:
1
uv publish
发布前建议确认项目的 pyproject.toml 中已经正确配置了包名、版本、构建系统、README、license 等元数据。
常见发布流程如下:
1
2
3
4
uv lock
uv sync
uv build
uv publish
如果你要发布给 PyPI,建议提前确认认证方式,例如 token、环境变量或 uv 的认证配置。
常用命令速查
| 场景 | 命令 |
|---|---|
| 创建项目 | uv init my-app |
| 添加运行时依赖 | uv add requests |
| 添加开发依赖 | uv add --dev pytest ruff |
| 移除依赖 | uv remove requests |
| 生成或更新锁文件 | uv lock |
| 严格同步环境 | uv sync |
| 运行脚本 | uv run python main.py |
| 查看依赖树 | uv tree |
| 安装 Python | uv python install 3.12 |
| 固定项目 Python 版本 | uv python pin 3.12 |
| 创建虚拟环境 | uv venv |
| pip 兼容安装 | uv pip install -r requirements.txt |
| 编译 requirements | uv pip compile requirements.in -o requirements.txt |
| 同步 requirements 环境 | uv pip sync requirements.txt |
| 临时运行工具 | uvx ruff check . |
| 全局安装工具 | uv tool install ruff |
| 构建包 | uv build |
| 发布包 | uv publish |
| 清理缓存 | uv cache clean |
| 升级 uv | uv self update |
推荐工作流
新项目推荐这样开始:
1
2
3
4
5
6
uv init my-app
cd my-app
uv python pin 3.12
uv add requests
uv add --dev pytest ruff
uv run python main.py
团队协作时,把这些文件提交到 Git:
1
2
3
pyproject.toml
uv.lock
.python-version
一般不要提交:
1
.venv/
其他成员拉取代码后执行:
1
uv sync
即可得到与锁文件一致的开发环境。
