Python 包管理的十年痛点
如果你写过 Python,一定被下面某个问题折磨过:pip install 慢到怀疑人生;装个 TensorFlow 就"依赖冲突";换台机器 requirements.txt 跑不起来;不记得哪个项目在哪个 venv 里;全局污染把系统 Python 搞崩了;Poetry 配置一堆花样但还是慢……
这些问题的根源在于 Python 生态的包管理工具是历史叠加出来的:pip 只管安装,venv 只管环境,pipx 管全局工具,Poetry/PDM 管锁文件,pyenv 管 Python 版本。五个工具各管一段,彼此不完全兼容。
uv 由 Astral 团队(也就是 Ruff 作者)开发,用 Rust 重写整条工具链,在一条命令里统一了上述所有工具的能力,并额外提供全局缓存、锁文件、工作区、自动 Python 下载等现代特性。它是 cargo(Rust)、npm(Node)那种"官方事实标准"在 Python 生态里的对位物。
核心名词解释
uv venv 的速度比原生 venv 快约 80 倍(几十毫秒 vs 几秒)。uv init、uv add、uv sync)定位类似 Poetry,但速度快 10 倍以上、锁文件格式更简单、与 PEP 标准(PEP 621/751/723)更贴合。uv tool install 与 uvx 完全替代 pipx。uv python install 3.13 即可下载对应版本,.python-version 文件配合使用,完全替代 pyenv。uv 为什么这么快?
速度不是玄学,uv 的性能来自几个工程决策:
- Rust 实现:相比 Python 写的 pip,启动开销(解释器初始化、模块导入)消失。
- 并发下载与解析:pip 是串行的,uv 同时解析多个候选版本、并发拉取 whl。
- 全局缓存 + 硬链接:同一个包只在磁盘存一份(
~/.cache/uv),项目 venv 通过硬链接/符号链接复用,避免重复复制。 - PubGrub 依赖解析算法:相比 pip 的回溯解析,PubGrub 冲突解释清晰、速度显著更快。
- 懒索引:只下载真正需要的包元数据(zip 中的 METADATA 文件),不盲目下完整个 wheel。
uv vs 其他方案对比
| 能力 | pip + venv | Poetry | Conda | uv |
|---|---|---|---|---|
| 安装速度(冷) | 基准 1× | ~0.8× | ~0.3× | 10-30× |
| 锁文件 | ❌(需 pip-tools) | ✅ poetry.lock | ✅ environment.yml | ✅ uv.lock |
| 自动管 Python 版本 | ❌ | ❌(需 pyenv) | ✅ | ✅ |
| 全局工具隔离 | ❌(需 pipx) | ❌ | 部分 | ✅ uv tool |
| Workspace / Monorepo | ❌ | ✅(有限) | ❌ | ✅ 原生 |
| PEP 621 pyproject | 部分 | 不完全(自定义 section) | ❌ | ✅ 完全 |
| 学习曲线 | 低 | 中 | 高 | 低 |
安装 uv
macOS / Linux(推荐官方安装脚本)
# 一键脚本(自动下载预编译二进制,不需要 Python)
curl -LsSf https://astral.sh/uv/install.sh | sh
# 或使用 Homebrew
brew install uv
# 验证
uv --version
# uv 0.5.x (xxxxxxx 2026-xx-xx)
Windows
# PowerShell 官方脚本
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
# 或 winget / scoop
winget install --id=astral-sh.uv
scoop install uv
通过 pip / pipx 安装(不推荐但可用)
# 这需要你已经有 Python,失去了"自动管 Python"能力
pip install uv
# 或
pipx install uv
uv 是一个独立的 Rust 二进制,不需要 Python 解释器。官方脚本直接下载预编译好的 musl/glibc/macOS/Windows 二进制到 ~/.local/bin/uv,冷启动更快、也不会被某个 venv 污染。pip install uv 是"用 Python 装管 Python 的工具"——鸡生蛋的循环,应避免。
Shell 补全
# zsh(macOS 默认)
echo 'eval "$(uv generate-shell-completion zsh)"' >> ~/.zshrc
# bash
echo 'eval "$(uv generate-shell-completion bash)"' >> ~/.bashrc
# fish
echo 'uv generate-shell-completion fish | source' >> ~/.config/fish/config.fish
# 也给 uvx(一次性运行工具)配上
echo 'eval "$(uvx --generate-shell-completion zsh)"' >> ~/.zshrc
uv 命令速览
uv 的子命令按"用途"分组,第一次看完这张表就对整个工具有全局感:
uv init 创建项目|uv add 加依赖|uv remove 移除|uv sync 同步环境|uv lock 重新生成锁文件|uv run 在项目环境运行命令uv python install 3.13 下载|uv python list 查看|uv python pin 固定版本|uv python find 查找uv tool install ruff 全局装|uv tool list/upgrade/uninstall|uvx black 一次性运行uv venv 创建 venv(默认在 .venv)|uv pip install pip 兼容接口uv build 生成 wheel/sdist|uv publish 上传到 PyPI第一次体验:Hello uv
别急着读后面 9 章,先动手跑一遍,把整个流程跑通:
# 1. 创建项目
uv init hello-uv
cd hello-uv
# 2. 添加一个包(uv 会自动创建 .venv、下载 Python、更新 pyproject.toml 和 uv.lock)
uv add requests
# 3. 写点代码
cat > main.py << 'EOF'
import requests
r = requests.get("https://httpbin.org/json")
print(r.json())
EOF
# 4. 运行(无需激活 venv)
uv run main.py
# 5. 查看生成的文件
ls -la
# .python-version .venv/ main.py pyproject.toml uv.lock
uv add requests 背后做了七件事:检测是否已有 Python → 如果没有,自动下载 → 创建 .venv → 解析依赖 → 下载 whl → 安装 → 更新 pyproject.toml 和 uv.lock。换做 pip + venv + requirements.txt,你要手动敲 5 条命令并维护一堆文件。
环境变量与配置
uv 的行为可以通过环境变量和配置文件调整,常用的几个:
UV_CACHE_DIR:全局缓存目录,默认~/.cache/uv。团队共享 CI runner 可改到更持久的磁盘。UV_PYTHON:默认 Python 版本,例如UV_PYTHON=3.13。UV_INDEX_URL:自定义 PyPI 镜像(国内常设为清华/阿里)。UV_NO_SYNC:在uv run前跳过自动同步,适合容器内缩短启动。- 全局配置文件:
~/.config/uv/uv.toml(Linux/macOS)。
# ~/.config/uv/uv.toml — 设置国内镜像
[[index]]
name = "tsinghua"
url = "https://pypi.tuna.tsinghua.edu.cn/simple"
default = true
uv 是 Astral 用 Rust 重写的 Python 工具链,一条命令替代 pip/venv/pipx/poetry/pyenv 五个老工具,速度快 10-100 倍。今天就装上、从新项目用起、保持老项目按需迁移是最稳妥的策略。下一章我们进入项目模式,深入 pyproject.toml 和 uv init 背后的 PEP 621 标准。