Python uv 包管理器 2026:比 pip 快 10 倍的依赖管理终极指南
Python 依赖管理的至暗时刻
每个 Python 开发者都经历过这些痛苦:
- pip 安装慢如蜗牛:一个 Django 项目
pip install动辄几分钟,依赖解析卡在Collecting阶段让人抓狂 - poetry 配置复杂如天书:
pyproject.toml的依赖分组、extras、source 配置让人头大,lock 文件冲突更是家常便饭 - venv 手动管理繁琐:
python -m venv .venv、source .venv/bin/activate、deactivate……每个项目都要重复这套流程 - Python 版本切换混乱:pyenv、conda、系统 Python 互相打架,
which python永远不知道指向哪个 - 依赖锁定不可靠:
requirements.txt没有锁文件,pip freeze > requirements.txt生成的依赖包含间接依赖,环境无法复现
2024 年,Astral 团队(ruff 的创造者)推出了 uv——一个用 Rust 编写的 Python 包管理器,速度比 pip 快 10-100 倍。到 2026 年,uv 已经成为 Python 生态中最受瞩目的包管理工具,支持项目管理、虚拟环境、Python 版本管理、Monorepo 工作区等全栈能力。
本文将从核心概念出发,通过 5 大实战模式,带你全面掌握 uv 的使用。
核心概念速查
| 概念 | 说明 | 对应命令 |
|---|---|---|
| 项目管理 | 初始化项目、管理依赖声明 | uv init、uv add、uv remove |
| 虚拟环境 | 自动创建和管理 .venv | uv venv、uv sync |
| Python 版本管理 | 安装和切换 Python 解释器 | uv python install、uv python pin |
| 依赖锁定 | 生成可复现的锁文件 | uv lock(自动生成 uv.lock) |
| 依赖解析 | 高性能解析依赖树 | 内置 Rust 解析器,10-100x 速度提升 |
| 工作区 | Monorepo 多包管理 | uv workspace |
| 工具运行 | 临时安装并运行 CLI 工具 | uv tool run、uvx |
| 脚本执行 | 内联依赖声明并运行脚本 | uv run script.py |
| 缓存管理 | 全局包缓存,避免重复下载 | uv cache |
| 导出依赖 | 导出为 requirements.txt 格式 | uv export |
五大核心挑战分析
挑战一:依赖解析速度
pip 使用回溯解析算法,复杂依赖图可能需要数分钟甚至解析失败。uv 采用基于 SAT 求解器的高性能解析器,通常在毫秒级完成解析。
挑战二:环境一致性
requirements.txt 不包含完整的依赖锁定信息,不同机器安装结果可能不同。uv 的 uv.lock 锁文件记录完整的依赖树哈希,确保任何环境都能精确复现。
挑战三:Python 版本碎片化
不同项目需要不同 Python 版本,pyenv + venv 的组合配置繁琐。uv 内置 Python 版本管理,一条命令安装切换,无需额外工具。
挑战四:Monorepo 依赖共享
多个子包之间有内部依赖关系,传统方案需要手动发布到私有 PyPI 或使用 pip install -e。uv workspace 原生支持 Monorepo,子包之间自动链接。
挑战五:CI/CD 缓存效率
pip 在 CI 中每次都要重新下载依赖,即使有缓存也经常 cache miss。uv 的全局缓存 + 内容寻址机制让 CI 缓存命中率接近 100%。
方案一:uv 安装与项目初始化
安装 uv
# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
# 使用 pip 安装(不推荐,仅作备用)
pip install uv
# 使用 Homebrew
brew install uv
# 验证安装
uv --version
# uv 0.7.12 (2026 年最新稳定版)
项目初始化
# 创建新项目
uv init my-project
cd my-project
# 查看项目结构
# my-project/
# ├── .python-version # Python 版本锁定
# ├── pyproject.toml # 项目配置和依赖声明
# ├── uv.lock # 依赖锁文件(自动生成)
# ├── hello.py # 示例入口文件
# └── .venv/ # 虚拟环境(自动创建)
依赖管理
# 添加依赖
uv add fastapi
uv add "sqlalchemy>=2.0"
uv add --dev pytest
uv add --dev ruff
# 添加可选依赖组
uv add --optional ml torch
# 移除依赖
uv remove pytest
# 同步依赖(安装 pyproject.toml 中声明的所有依赖)
uv sync
# 仅同步生产依赖(排除 dev)
uv sync --no-dev
# 同步指定分组
uv sync --group ml
pyproject.toml 结构
[project]
name = "my-project"
version = "0.1.0"
description = "A modern Python project"
requires-python = ">=3.12"
dependencies = [
"fastapi>=0.115.0",
"sqlalchemy>=2.0",
]
[project.optional-dependencies]
ml = [
"torch>=2.5",
"transformers>=4.45",
]
[tool.uv]
dev-dependencies = [
"pytest>=8.0",
"ruff>=0.8",
]
[tool.uv.sources]
my-private-pkg = { git = "https://github.com/myorg/my-private-pkg.git", tag = "v1.0.0" }
运行项目
# 在虚拟环境中运行脚本
uv run python hello.py
# 运行模块
uv run python -m my_project.main
# 运行带内联依赖声明的脚本
uv run --with requests python fetch_data.py
方案二:虚拟环境与 Python 版本管理
虚拟环境管理
# 创建虚拟环境(默认使用 .venv 目录)
uv venv
# 指定 Python 版本创建
uv venv --python 3.12
# 指定虚拟环境路径
uv venv /path/to/.venv
# 激活虚拟环境
# macOS / Linux
source .venv/bin/activate
# Windows
.venv\Scripts\activate
# uv sync 会自动创建虚拟环境
uv sync
Python 版本管理
# 查看可用 Python 版本
uv python list
# 安装指定 Python 版本
uv python install 3.12
uv python install 3.13
# 安装特定实现
uv python install pypy3.10
uv python install graalpy3.11
# 固定项目 Python 版本(写入 .python-version)
uv python pin 3.12
# 查看已安装版本
uv python list --only-installed
# 查找 Python 解释器路径
uv python find 3.12
# 临时使用指定版本运行
uv run --python 3.13 python --version
.python-version 文件
3.12
这个文件会被 uv 自动读取,确保团队成员使用一致的 Python 版本。配合 uv sync,新人 clone 项目后只需一条命令即可搭建完整环境。
多版本并行场景
# 项目 A 使用 Python 3.12
cd project-a
uv python pin 3.12
uv sync
# 项目 B 使用 Python 3.13
cd project-b
uv python pin 3.13
uv sync
# 两个项目互不干扰,无需 pyenv 切换
方案三:从 pip/requirements.txt 和 poetry/pyproject.toml 迁移
从 pip + requirements.txt 迁移
# 方式一:直接在现有项目中初始化
cd existing-project
uv init
# uv 会检测到已有的 requirements.txt 并自动导入
# 方式二:手动导入依赖
uv add $(cat requirements.txt | grep -v "^#" | grep -v "^$" | tr "\n" " ")
# 方式三:使用 uv pip 兼容模式(过渡期使用)
uv pip install -r requirements.txt
uv pip compile requirements.in -o requirements.txt
# 导出回 requirements.txt 格式
uv export > requirements.txt
uv export --no-dev > requirements-prod.txt
从 poetry 迁移
# uv 直接读取 poetry 的 pyproject.toml
cd poetry-project
uv init
# uv 会自动识别 [tool.poetry.dependencies] 并迁移
# 手动迁移步骤
# 1. 备份 poetry.lock
cp poetry.lock poetry.lock.bak
# 2. 将 poetry 依赖格式转为 PEP 621 格式
# poetry 格式:
# [tool.poetry.dependencies]
# fastapi = "^0.115.0"
# PEP 621 格式:
# [project]
# dependencies = ["fastapi>=0.115.0"]
# 3. 生成 uv.lock
uv lock
# 4. 同步依赖
uv sync
poetry 到 uv 的 pyproject.toml 转换脚本
import tomllib
import tomli_w
from pathlib import Path
def migrate_poetry_to_uv(pyproject_path: str = "pyproject.toml"):
""将 poetry 格式的 pyproject.toml 转换为 uv 兼容格式""
path = Path(pyproject_path)
data = tomllib.loads(path.read_text(encoding="utf-8"))
poetry_deps = data.get("TOOL", {}).get("poetry", {}).get("dependencies", {})
poetry_dev_deps = (
data.get("TOOL", {})
.get("poetry", {})
.get("group", {})
.get("dev", {})
.get("dependencies", {})
)
def convert_version(version_spec: str) -> str:
if isinstance(version_spec, dict):
return version_spec.get("version", "*")
if version_spec.startswith("^"):
base = version_spec[1:]
parts = base.split(".")
upper = f"{int(parts[0]) + 1}.0.0"
return f">={base},<{upper}"
if version_spec.startswith("~"):
base = version_spec[1:]
parts = base.split(".")
upper = f"{parts[0]}.{int(parts[1]) + 1}.0"
return f">={base},<{upper}"
return version_spec
dependencies = []
for name, version in poetry_deps.items():
if name == "python":
data.setdefault("project", {})["requires-python"] = f">={version}"
continue
dep = convert_version(version)
dependencies.append(f"{name}{dep}" if dep != "*" else name)
data.setdefault("project", {})["dependencies"] = dependencies
dev_dependencies = []
for name, version in poetry_dev_deps.items():
dep = convert_version(version)
dev_dependencies.append(f"{name}{dep}" if dep != "*" else name)
if dev_dependencies:
data.setdefault("TOOL", {}).setdefault("uv", {})[
"dev-dependencies"
] = dev_dependencies
if "poetry" in data.get("TOOL", {}):
del data["TOOL"]["poetry"]
path.write_text(tomli_w.dumps(data), encoding="utf-8")
print(f"迁移完成: {dependencies=}, {dev_dependencies=}")
if __name__ == "__main__":
migrate_poetry_to_uv()
从 pipenv 迁移
# 导出 Pipfile 依赖为 requirements.txt
pipenv requirements > requirements.txt
# 使用 uv 初始化并导入
uv init
uv add $(cat requirements.txt | tr "\n" " ")
uv sync
方案四:Monorepo 与工作区管理
工作区初始化
# 创建 Monorepo 根目录
mkdir my-monorepo && cd my-monorepo
uv init --workspace
# 创建子包
uv init --package libs/core
uv init --package libs/api
uv init --package apps/web
# 项目结构
# my-monorepo/
# ├── pyproject.toml # 工作区根配置
# ├── uv.lock # 全局锁文件(统一管理)
# ├── libs/
# │ ├── core/
# │ │ ├── pyproject.toml
# │ │ └── src/core/
# │ └── api/
# │ ├── pyproject.toml
# │ └── src/api/
# └── apps/
# └── web/
# ├── pyproject.toml
# └── src/web/
根 pyproject.toml 配置
[tool.uv.workspace]
members = [
"libs/core",
"libs/api",
"apps/web",
]
[tool.uv.sources]
core = { workspace = true }
api = { workspace = true }
子包 pyproject.toml
# libs/core/pyproject.toml
[project]
name = "core"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
"pydantic>=2.9",
]
# libs/api/pyproject.toml
[project]
name = "api"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
"core",
"fastapi>=0.115.0",
]
# apps/web/pyproject.toml
[project]
name = "web"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
"core",
"api",
"uvicorn>=0.32.0",
]
工作区操作
# 同步整个工作区
uv sync
# 仅同步指定子包
uv sync --package api
# 在指定子包中运行命令
uv run --package api python -m api.main
# 为指定子包添加依赖
uv add --package api httpx
# 构建指定子包
uv build --package core
# 发布指定子包
uv publish --package core
工作区依赖图验证
# 查看依赖树
uv tree
# 检查依赖冲突
uv lock --check
# 更新指定依赖
uv lock --upgrade-package fastapi
方案五:CI/CD 集成与 Docker 优化
GitHub Actions 集成
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v4
with:
version: "latest"
enable-cache: true
cache-dependency-glob: "uv.lock"
- name: Set up Python
run: uv python install 3.12
- name: Install dependencies
run: uv sync --frozen
- name: Run linter
run: uv run ruff check .
- name: Run tests
run: uv run pytest --cov=src --cov-report=xml
- name: Upload coverage
uses: codecov/codecov-action@v4
GitLab CI 集成
# .gitlab-ci.yml
stages:
- test
- build
test:
stage: test
image: python:3.12-slim
before_script:
- pip install uv
- uv python install 3.12
- uv sync --frozen
script:
- uv run ruff check .
- uv run pytest --cov=src
cache:
key:
files:
- uv.lock
paths:
- .venv/
- ~/.cache/uv/
build:
stage: build
image: python:3.12-slim
before_script:
- pip install uv
script:
- uv build
artifacts:
paths:
- dist/
Docker 多阶段构建优化
# Dockerfile
FROM ghcr.io/astral-sh/uv:latest AS uv
FROM python:3.12-slim AS deps
COPY --from=uv /uv /usr/local/bin/uv
WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-install-project --no-dev
FROM python:3.12-slim AS runtime
WORKDIR /app
COPY --from=deps /app/.venv /app/.venv
COPY . .
ENV PATH="/app/.venv/bin:$PATH"
ENV VIRTUAL_ENV="/app/.venv"
CMD ["python", "-m", "my_project.main"]
Docker Compose 开发环境
# docker-compose.yml
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "8000:8000"
volumes:
- .:/app
- uv-cache:/root/.cache/uv
environment:
- PYTHONUNBUFFERED=1
command: uv run uvicorn my_project.main:app --host 0.0.0.0 --reload
volumes:
uv-cache:
CI 缓存优化技巧
# 使用 --frozen 确保不修改锁文件(CI 环境必须)
uv sync --frozen
# 使用 --no-dev 减少安装量
uv sync --frozen --no-dev
# 离线安装(依赖已缓存时)
uv sync --frozen --offline
常见陷阱指南
陷阱一:混用 pip 和 uv
❌ 在 uv 管理的项目中用 pip install 安装依赖,绕过 uv 的依赖管理
✅ 始终使用 uv add 添加依赖,uv sync 同步环境。如需临时安装,用 uv pip install(兼容模式)
陷阱二:忽略 uv.lock 提交
❌ 将 uv.lock 加入 .gitignore,导致团队成员依赖版本不一致
✅ 将 uv.lock 提交到版本控制,确保所有环境使用相同的依赖版本。CI 中使用 --frozen 防止意外更新
陷阱三:忘记固定 Python 版本
❌ 不设置 .python-version,不同开发者使用不同 Python 版本导致兼容性问题
✅ 使用 uv python pin 3.12 固定版本,并将 .python-version 提交到仓库
陷阱四:全局安装污染
❌ 使用 uv tool install 安装大量全局工具,版本冲突难以排查
✅ 项目级工具使用 uv run --with 临时安装运行;全局工具仅安装高频使用的(如 ruff、black)
陷阱五:Docker 中不利用缓存层
❌ 先 COPY 全部代码再 uv sync,每次代码变更都重新安装依赖
✅ 先 COPY pyproject.toml + uv.lock,再 uv sync,最后 COPY 代码。利用 Docker 缓存层避免重复安装
错误排错表
| 错误现象 | 可能原因 | 解决方案 |
|---|---|---|
error: No virtual environment found |
未创建虚拟环境 | 运行 uv sync 或 uv venv 自动创建 |
error: Failed to download package |
网络问题或 PyPI 源不可达 | 配置镜像源:uv pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple |
error: Python 3.12 not found |
未安装对应 Python 版本 | 运行 uv python install 3.12 |
error: Lockfile is out of date |
pyproject.toml 更新但未重新 lock | 运行 uv lock 更新锁文件 |
error: Resolution failed |
依赖版本冲突 | 检查 pyproject.toml 中的版本约束,使用 uv tree 查看依赖树 |
error: Package not found in workspace |
工作区成员配置错误 | 检查 [tool.uv.workspace] 的 members 路径 |
uv sync 速度慢 |
缓存未命中或网络延迟 | 检查缓存目录权限,配置镜像源,使用 --offline 模式 |
error: Hash mismatch |
依赖包被篡改或缓存损坏 | 运行 uv cache clean 清除缓存后重试 |
error: Cannot activate venv |
虚拟环境损坏 | 删除 .venv 目录后重新 uv sync |
error: Unsupported Python version |
Python 版本不满足 requires-python | 运行 uv python install 安装满足要求的版本 |
高级优化技巧
1. 镜像源加速
# 配置清华镜像源(中国大陆推荐)
uv pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
# 或在 pyproject.toml 中配置
# [tool.uv]
# index-url = "https://pypi.tuna.tsinghua.edu.cn/simple"
# 多源配置(私有 PyPI + 公共源)
# [tool.uv]
# extra-index-url = ["https://pypi.mycompany.com/simple/"]
2. 缓存管理
# 查看缓存信息
uv cache dir
uv cache list
# 清除缓存
uv cache clean
# 清除特定包的缓存
uv cache clean numpy
# 查看缓存大小
du -sh $(uv cache dir)
3. 离线环境部署
# 导出依赖到 vendor 目录
uv export --no-dev > requirements.txt
uv pip download -r requirements.txt -d vendor/
# 离线安装
uv pip install --no-index --find-links vendor/ -r requirements.txt
4. 脚本内联依赖
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "requests>=2.32",
# "rich>=13.0",
# ]
# ///
import requests
from rich import print
response = requests.get("https://httpbin.org/json")
print(response.json())
# 直接运行,uv 自动安装依赖
uv run script.py
5. 依赖安全审计
# 检查已知漏洞
uv audit
工具对比选型
| 维度 | uv | pip | poetry | pdm | conda |
|---|---|---|---|---|---|
| 依赖解析速度 | 极快(Rust) | 慢(回溯) | 中等 | 快 | 慢 |
| 虚拟环境管理 | 内置 | 需 venv | 内置 | 内置 | 内置 |
| Python 版本管理 | 内置 | 需 pyenv | 需 pyenv | 内置 | 内置 |
| 锁文件 | uv.lock | 无 | poetry.lock | pdm.lock | 无 |
| Monorepo 支持 | 原生工作区 | 不支持 | 不支持 | 有限 | 不支持 |
| CI 缓存友好 | 极好 | 一般 | 好 | 好 | 差 |
| 配置复杂度 | 低 | 低 | 高 | 中 | 高 |
| 生态成熟度 | 快速成长 | 最成熟 | 成熟 | 成长中 | 成熟 |
| 学习曲线 | 平缓 | 平缓 | 陡峭 | 中等 | 陡峭 |
| 包数量 | PyPI 全量 | PyPI 全量 | PyPI 全量 | PyPI 全量 | Anaconda + PyPI |
| 跨语言支持 | 仅 Python | 仅 Python | 仅 Python | 仅 Python | 多语言(C/C++/R) |
| 推荐指数 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ |
选型建议:
- 新项目首选 → uv(全栈能力、极速体验)
- 已有 poetry 项目 → 逐步迁移到 uv(兼容读取 poetry 配置)
- 数据科学/ML 项目 → uv + conda 互补(uv 管理纯 Python 包,conda 管理 C/C++ 依赖)
- 简单脚本/一次性任务 → uv run(无需初始化项目)
相关工具推荐
在 Python 项目开发中,以下 工具库 工具可以帮到你:
- JSON 格式化 — 格式化 API 响应和配置文件,排查 pyproject.toml 中的 JSON 数据问题
- Hash 计算 — 计算依赖包哈希值,验证下载完整性
- cURL 转代码 — 将 API 请求一键转为 Python 代码,快速构建 HTTP 客户端
Python 依赖管理经历了从
easy_install到pip,从requirements.txt到poetry.lock的漫长演进。uv 的出现不是简单的替代,而是将 Rust 的高性能与 Python 的易用性完美结合,让依赖管理从「不得不忍受的痛点」变成「几乎无感的体验」。2026 年,uv 已经准备好成为你的默认选择。
本站提供浏览器本地工具,免注册即可试用 →