🚀 Python 开发者的新神器:uv 全面指南
如果你是一名 Python 开发者,那么你大概率经历过这样的场景:
pipinstallxxx然后……
等。
安装几个依赖还好,如果项目依赖比较复杂,可能还会遇到:
依赖冲突 版本不一致 虚拟环境混乱 requirements.txt 不准确 不同电脑安装结果不同 Python 版本管理麻烦于是 Python 社区出现了很多工具:
pip:安装 Python 包venv:创建虚拟环境pip-tools:锁定依赖virtualenv:虚拟环境管理Poetry:项目和依赖管理pyenv:Python 版本管理pipx:管理 Python CLI 工具
每个工具都解决一个问题。
但问题也来了:
为什么 Python 项目环境管理不能像 Rust 的 Cargo 一样,一个工具全部搞定?
这正是uv想解决的问题。
一、uv 到底是什么?
uv 是由Astral开发的 Python 包管理和项目管理工具。
Astral 也是著名 Python 工具Ruff的开发团队。
uv 使用Rust编写,最初定位是一个非常高速的 Python package installer 和 resolver,也就是:
高速安装 Python 包 + 高速解析 Python 依赖。
uv 在 2024 年 2 月正式发布,最开始主要被定位为pip和pip-tools的高速替代品。官方早期测试中,uv 在无缓存场景下相比 pip/pip-tools 可以达到约 8~10 倍速度,而在暖缓存场景下曾达到约 80~115 倍的速度。(Astral)
当然,实际速度会受到:
- 网络
- CPU
- 磁盘
- Python 包类型
- 是否命中缓存
- 操作系统
等因素影响。
所以网上经常看到的:
“uv 比 pip 快 100 倍”
更准确地说应该理解成:
在特定依赖安装和缓存场景下,uv 可以比传统 Python 工具快很多,而不是任何情况下都固定快 100 倍。
二、uv 为什么会出现?
要理解 uv,首先要理解 Python 原来的工具链。
传统 Python 项目经常是这样的:
Python │ ├── pip │ └── 安装依赖 │ ├── venv │ └── 创建虚拟环境 │ ├── requirements.txt │ └── 保存依赖 │ ├── pip-tools │ └── 锁定依赖 │ ├── pyenv │ └── 管理 Python 版本 │ └── pipx └── 管理 CLI 工具这套体系当然可以工作。
但是对于现代 Python 项目来说,开发者需要在不同工具之间来回切换。
例如:
python-mvenv .venvsource.venv/bin/activate pipinstallrequests pip freeze>requirements.txtWindows 还需要:
.venv\Scripts\activate如果需要换 Python 版本,又需要另外解决。
如果需要安装 Ruff、Black 这种 CLI 工具,又可能考虑pipx。
这就产生了一个非常明显的问题:
Python 的工具链比较碎片化。
而 Rust 的体验就非常统一。
例如:
cargonew my-projectcargoaddserdecargobuildcargoruncargotest所以 Astral 在 uv 的设计目标中提出了一个很有意思的方向:
Cargo for Python。
也就是:
希望 Python 也拥有类似 Cargo 的统一项目管理体验。
Astral 在 2024 年 8 月进一步宣布 uv 从单纯的 pip 替代品扩展到完整的 Python 项目、命令行工具、单文件脚本以及 Python 本身的管理。(Astral)
三、为什么 uv 使用 Rust?
这是 uv 最大的特点之一。
传统 Python 包管理工具大量使用 Python 实现,而 uv 使用 Rust。
为什么?
因为包管理器本身需要大量进行:
- 网络请求
- 文件操作
- ZIP/TAR 解压
- 包元数据解析
- 依赖关系解析
- 哈希计算
- 缓存管理
- 并发任务
这些任务非常适合使用 Rust 构建。
而且 uv 并不依赖 Python 才能运行。
这意味着:
没有 Python ↓ 也可以安装 uv ↓ uv 安装 Python ↓ uv 创建虚拟环境 ↓ uv 安装项目依赖这就是一个非常重要的改变。
官方文档也明确说明,uv 可以在没有预先安装 Python 或 Rust 的情况下,通过独立安装器进行安装。(Astral 文档)
四、安装 uv
Linux / macOS
可以使用官方安装脚本:
curl-LsSfhttps://astral.sh/uv/install.sh|sh安装完成以后:
uv--version例如:
uv 0.x.xWindows
PowerShell:
powershell-ExecutionPolicy ByPass-c"irm https://astral.sh/uv/install.ps1 | iex"也可以使用:
winget install--id=astral-sh.uv-e官方目前还提供 Homebrew、Scoop、Docker、PyPI 等多种安装方式。(Astral 文档)
五、第一条 uv 命令
安装完成以后,直接:
uv你会发现 uv 并不是只有:
uvinstall这么简单。
它已经形成了一套完整的 CLI:
uv init uv add uv remove uv run uv sync uv lock uv export uv tree uv python uv venv uv pip uv tool uv build uv publish uv cache uv self官方 CLI 当前已经覆盖项目管理、依赖管理、Python 管理、工具管理、构建和发布等多个场景。(Astral 文档)
六、创建第一个 Python 项目
这是我最推荐新项目使用 uv 的方式。
直接:
uv init my-project然后:
cdmy-project你会看到类似:
my-project/ ├── .gitignore ├── .python-version ├── README.md ├── main.py └── pyproject.toml其中最重要的是:
pyproject.toml它是现代 Python 项目的核心配置文件。
七、uv add:添加依赖
比如我们需要安装:
requests以前可能:
pipinstallrequests现在:
uvaddrequestsuv 会自动完成依赖解析和环境同步。
如果需要指定版本:
uvadd"requests>=2.30"指定固定版本:
uvadd"requests==2.32.3"开发依赖也可以进行单独管理。
例如:
uvadd--devpytest然后项目的pyproject.toml会记录依赖。
这种方式比手动:
pipinstallxxx pip freeze>requirements.txt更加适合现代项目。
八、uv remove:删除依赖
如果不需要某个包:
uv remove requestsuv 会同时更新项目依赖配置以及环境。
九、uv sync:同步环境
这是 uv 非常重要的一条命令:
uvsync它的核心思想是:
让当前环境与项目定义的依赖保持一致。
例如你从 GitHub 拉下来一个项目:
gitclone xxxcdproject通常你需要:
pipinstall-rrequirements.txt而 uv 项目一般直接:
uvsyncuv 会根据项目配置和锁文件准备环境。
十、uv.lock 是什么?
这是 uv 最重要的设计之一。
项目通常会有:
pyproject.toml uv.lock其中:
pyproject.toml
描述:
我想要什么依赖。
例如:
dependencies = [ "requests>=2.30", "fastapi>=0.100" ]而:
uv.lock
描述:
最终到底安装哪些具体版本。
例如:
fastapi 0.x.x requests 2.x.x starlette 0.x.x urllib3 2.x.x这样团队成员执行:
uvsync理论上可以得到更加一致的依赖环境。
十一、uv lock
如果你只是想更新锁文件:
uv lock它会重新进行依赖解析并更新:
uv.lock在团队开发中,一般建议:
pyproject.toml + uv.lock ↓ Git 提交 ↓ 其他开发者 ↓ uv sync这样环境一致性会明显提高。
十二、uv run:不用 activate 也能运行
这是 uv 很舒服的一点。
传统方式:
source.venv/bin/activate python main.pyWindows:
.venv\Scripts\activate python main.py使用 uv:
uv run python main.py甚至:
uv run pytest或者:
uv run ruff check.uv 会自动使用项目环境。
所以很多情况下:
你甚至不需要手动 activate 虚拟环境。
十三、uv run 的一个重要特点
例如:
uv run pythonuv 会检查:
项目配置 ↓ 锁文件 ↓ 虚拟环境 ↓ 依赖 ↓ Python然后准备运行环境。
这使得:
uv run python main.py成为非常适合项目执行的标准方式。
十四、uv venv:创建虚拟环境
如果你仍然希望像传统 Python 一样手动创建环境:
uv venv默认会创建:
.venv/也可以指定 Python:
uv venv--python3.12甚至:
uv venv--python3.11官方文档也建议使用虚拟环境来隔离项目依赖。(Astral 文档)
十五、uv python:直接管理 Python
这可能是 uv 最让人惊喜的能力之一。
以前 Python 开发者可能需要:
pyenv conda 官方 Python installer Windows Store现在可以直接:
uv pythoninstall3.12安装 Python 3.12。
安装 Python 3.11:
uv pythoninstall3.11一次安装多个:
uv pythoninstall3.113.12查看 Python:
uv python list查找 Python:
uv pythonfind固定项目 Python 版本:
uv python pin3.12官方文档目前支持 uv 自动安装和管理多个 Python 版本,也支持 CPython、PyPy 等实现。(Astral 文档)
十六、Python 版本固定
例如项目要求:
Python 3.12可以:
uv python pin3.12然后项目中会出现:
.python-version这样团队成员进入项目后,就能够知道:
这个项目推荐使用哪个 Python 版本。
对于大型项目非常有用。
十七、uv pip:兼容传统 pip 工作流
如果你暂时不想迁移整个项目,也没关系。
uv 提供了:
uv pip它提供与常见 pip 工作流相似的接口。
例如:
uv pipinstallrequests卸载:
uv pip uninstall requests查看:
uv pip list查看具体包:
uv pip show requests冻结:
uv pip freeze检查:
uv pip check官方特别强调:
uv pip并不是调用 pip。
它只是提供了一个兼容 pip 使用习惯的低层接口。(Astral 文档)
十八、pip → uv pip
如果你现在项目大量使用 pip,可以非常平滑地迁移。
原来:
pipinstallrequests变成:
uv pipinstallrequests原来:
pip uninstall requests变成:
uv pip uninstall requests原来:
pip list变成:
uv pip list原来:
pip freeze变成:
uv pip freeze这也是 uv 能够快速流行的重要原因之一:
迁移成本非常低。
十九、requirements.txt 怎么办?
如果你的项目已经有:
requirements.txt可以:
uv pipinstall-rrequirements.txt也可以使用:
uv pipsyncrequirements.txt两者有一个重要区别。
install更接近传统安装行为。
而:
uv pipsync会尝试让环境与 requirements 文件保持一致,多余的包可能会被移除。官方文档明确说明,uv pip sync会删除 requirements 文件中未列出的包。(Astral 文档)
二十、uv pip compile
如果你的项目仍然使用:
requirements.in可以:
uv pip compile requirements.in-orequirements.txt例如:
requirements.in里面只有:
fastapi requests pydantic然后:
uv pip compile requirements.in-orequirements.txtuv 会解析完整依赖关系。
最终生成:
requirements.txt里面可能包含大量间接依赖。
这就类似于:
pip-tools的工作流。
二十一、uv tree:查看依赖关系
项目依赖越来越复杂以后,一个非常实用的命令就是:
uv tree例如:
my-project ├── fastapi │ ├── starlette │ └── pydantic │ └── annotated-types └── requests ├── urllib3 ├── certifi └── charset-normalizer这样可以快速理解:
一个 Python 包到底依赖了什么。
排查:
为什么装了这么多包? 为什么出现版本冲突? 谁依赖了这个包?都会非常方便。
二十二、uv tool:管理 Python CLI 工具
Python 生态有大量 CLI 工具:
ruff black httpie yt-dlp pre-commit cookiecutter以前很多人会使用:
pipxinstallruff现在可以使用:
uv toolinstallruff运行:
uv tool run ruff check.或者简写:
uvx ruff check.这种方式特别适合:
我只想使用一个 Python CLI 工具,不想把它安装到当前项目环境。
二十三、uvx 是什么?
可以把:
uvx理解成:
临时运行 Python CLI 工具。
例如:
uvx ruff check.你不需要先:
pipinstallruff也不需要污染当前项目环境。
这对于开发工具非常方便。
例如:
uvx black.或者:
uvx pytest二十四、uv run 单文件脚本
uv 甚至可以管理单文件 Python 脚本。
例如:
# hello.pyimportrequestsprint(requests.get("https://example.com"))传统情况下:
pipinstallrequests python hello.py而 uv 可以让脚本声明自己的依赖。
例如通过 PEP 723 内联元数据描述依赖,然后:
uv run hello.pyuv 会根据脚本声明准备运行环境。
官方 CLI 文档目前明确支持uv run --script以及 PEP 723 风格的脚本依赖管理。(Astral 文档)
这对于:
数据处理脚本 自动化脚本 爬虫 AI Demo 一次性工具 运维脚本非常实用。
二十五、uv cache:为什么 uv 越用越快?
uv 有自己的缓存系统。
可以查看:
uv cachedir管理缓存:
uv cache clean为什么缓存很重要?
假设你有:
项目 A 项目 B 项目 C三个项目都需要:
requests pydantic numpy传统方式可能需要重复下载或者重新处理。
uv 会尽可能利用缓存。
因此:
第一次安装 ↓ 下载 + 构建 + 缓存 ↓ 第二个项目 ↓ 命中缓存 ↓ 更快这也是 uv 在很多重复安装场景中速度非常快的重要原因。
二十六、uv 的核心架构思路
如果从整体上理解 uv,可以把它看成:
uv │ ┌─────────────┼─────────────┐ ↓ ↓ ↓ Python管理 项目管理 包管理 │ │ │ uv python uv init uv add uv venv uv run uv remove uv sync uv lock uv tree uv export │ │ │ └─────────────┼─────────────┘ ↓ uv cache而对于传统 pip 用户,还有:
uv pip │ ┌───────────┼───────────┐ ↓ ↓ ↓ install compile sync所以 uv 并不是简单的:
“一个更快的 pip。”
现在更准确的理解应该是:
uv 是一个统一的 Python 工具链。
二十七、uv 和 pip 的区别
简单来看:
| 能力 | pip | uv |
|---|---|---|
| 安装 Python 包 | ✅ | ✅ |
| 依赖解析 | ✅ | ✅ |
| 虚拟环境 | ❌ | ✅ |
| Python 版本管理 | ❌ | ✅ |
| 项目初始化 | ❌ | ✅ |
| Lockfile | 传统方式较弱 | ✅ |
| CLI 工具管理 | ❌ | ✅ |
| 项目运行 | ❌ | ✅ |
| Rust 实现 | ❌ | ✅ |
| 高性能缓存 | 有缓存 | 强调全局缓存 |
| 工作流统一 | 一般 | 很强 |
但这里需要注意:
pip 并没有“过时”。
pip 仍然是 Python 官方生态中极其重要的基础工具。
uv 的价值更像是:
在保留 pip 工作流兼容性的同时,把 Python 项目管理体验进一步统一。
二十八、uv 和 Poetry 有什么区别?
Poetry 也是非常成熟的 Python 项目管理工具。
两者都可以:
项目管理 依赖管理 虚拟环境 锁文件但理念略有区别。
Poetry 更早就走向:
完整 Python 项目管理工具。
而 uv 的路线是:
高速包安装 ↓ 高速依赖解析 ↓ pip 兼容 ↓ 项目管理 ↓ Python 管理 ↓ 工具管理 ↓ 脚本管理因此 uv 更强调:
速度 + 统一工具链 + 低迁移成本。
二十九、uv 和 Conda 有什么区别?
Conda 不只是 Python 包管理器。
它还擅长:
Python C/C++ CUDA 系统库 科学计算环境尤其是:
机器学习 数据科学 CUDA 复杂二进制依赖Conda 依然非常有价值。
而 uv 更偏向:
现代 Python 项目开发。
如果你是:
FastAPI Django Flask AI Agent RAG 爬虫 自动化 Web 后端 普通 Python 软件uv 会非常舒服。
如果你大量依赖:
CUDA 系统级科学计算库 Conda channel那么 Conda 仍然有它的优势。
三十、一个真实项目应该怎么使用 uv?
假设我们开发一个:
AI RAG 项目第一步:
uv init rag-project进入:
cdrag-project指定 Python:
uv python pin3.12安装:
uvaddfastapi uvaddpydantic uvaddopenai uvaddchromadb开发依赖:
uvadd--devpytest uvadd--devruff同步:
uvsync运行:
uv run python main.py测试:
uv run pytest代码检查:
uv run ruff check.查看依赖:
uv tree最后提交:
pyproject.toml uv.lock .python-version到 Git。
团队成员拿到项目以后:
gitclone xxxcdrag-project uvsync然后:
uv run python main.py整个过程就完成了。
三十一、推荐的现代 Python 项目结构
如果是我现在开始一个新的 Python 项目,我会倾向于:
my-project/ │ ├── .venv/ ├── .python-version ├── pyproject.toml ├── uv.lock ├── README.md ├── src/ │ └── my_project/ │ ├── __init__.py │ └── main.py │ └── tests/ └── test_main.py然后日常开发:
uvsync运行:
uv run python-mmy_project.main安装依赖:
uvaddxxx删除:
uv remove xxx测试:
uv run pytest代码检查:
uv run ruff check.这套工作流已经非常接近:
Python 版 Cargo。
三十二、最常用 uv 命令速查表
如果不想记几十个命令,可以先记下面这些:
项目
uv init uv run uvadduv remove uvsyncuv lock uv treePython
uv python list uv pythoninstall3.12uv pythonfinduv python pin3.12uv python uninstall3.12虚拟环境
uv venv uv venv--python3.12pip 兼容
uv pipinstallxxx uv pip uninstall xxx uv pip list uv pip freeze uv pip check uv pip compile uv pipsync工具
uv toolinstallruff uv tool list uv tool uninstall ruff uvx ruff缓存
uv cachediruv cache clean版本
uv--versionuv self update三十三、从 pip 迁移到 uv,应该怎么做?
如果你已经有一个老项目:
requirements.txt不建议一上来就全部重构。
可以先:
uv venv然后:
uv pipinstall-rrequirements.txt确认项目正常运行。
之后再逐步迁移:
requirements.txt ↓ pyproject.toml ↓ uv.lock最终变成:
uvsyncuv run uvadduv remove如果项目非常老,或者存在特殊安装逻辑,则应该逐步迁移,而不是一次性全部替换。
三十四、uv 最大的价值到底是什么?
很多文章喜欢把 uv 的卖点总结成:
快!
这当然没错。
但是我认为:
速度只是 uv 最容易被看到的优点,而统一才是它真正重要的地方。
以前:
pip venv virtualenv pip-tools pyenv pipx Poetry现在可以逐渐统一成:
uv │ ┌──────────┼──────────┐ ↓ ↓ ↓ Python Project Tools │ │ │ uv python uv add uv tool uv venv uv sync uvx uv run uv lock这才是 uv 最值得关注的地方。
三十五、总结:Python 的包管理正在发生变化
过去 Python 开发的经典组合是:
python + pip + venv + requirements.txt后来出现:
Poetry Pipenv Conda PDM Rye而 uv 的路线更加激进:
Python版本管理 + 虚拟环境 + 包安装 + 依赖解析 + 项目管理 + Lockfile + CLI工具 + 单文件脚本 + 构建发布全部逐渐整合到一个工具中。
尤其对于新项目,我认为非常值得尝试下面这一套:
uv init my-projectcdmy-project uv python pin3.12uvaddfastapi uvaddpydantic uvadd--devpytest uvsyncuv run python main.py uv run pytest你会发现整个 Python 项目的依赖管理过程变得非常简单。
如果你以前一直使用:
pipinstallpython-mvenv pip freeze requirements.txt那么完全可以先从:
uv pipinstallxxx开始体验。
如果感觉不错,再逐渐迁移到:
uv init uvadduvsyncuv run uv lock这时候你就会真正理解为什么很多 Python 开发者会把 uv 称为:
“Python 生态里的 Cargo。”
而这可能才是 uv 真正有意思的地方。