Python
生态向来不缺包管理和环境管理工具,从经典的 pip
、virtualenv
到 pip-tools
、conda
,再到现代化的 Poetry
、PDM
等等。每种工具都有其擅长的领域,但也常常让开发者的工具链变得零散和复杂。
现在,来自 Astral
公司(知名 Python
Linter Ruff
的缔造者)的 uv
横空出世,带来了新的可能性。这款使用 Rust
语言编写的工具,立志成为一个 速度飞快、功能统一且对开发者友好的 Python
包和项目管理器。它的目标很明确:借鉴 Rust
生态中 Cargo
的成功经验,提供一站式的解决方案。uv
不仅仅是快,它还将环境管理、包安装、依赖解析、项目管理等功能整合到了一起。
为何关注 UV?
与现有工具相比,uv
提供了一个更现代、高效的选择,其核心亮点在于:
- 显著的速度提升:基于
Rust
的编译时优化和高效的并发处理能力,uv
在依赖解析、包安装等常见操作上,其速度相比传统工具如pip
或Poetry
,往往能快上几个数量级。内置的高效全局缓存机制,也让重复操作几乎瞬时完成。这背后是Rust
语言特性(如内存安全带来的无畏并发)和高质量底层库(如Tokio
、Reqwest
)的功劳。 - 全面的功能集成:
uv
意图成为开发者手中的“瑞士军刀”,覆盖从创建和管理虚拟环境、安装和锁定依赖(原生支持pyproject.toml
,兼容requirements.txt
),到运行脚本、管理全局工具,乃至安装特定Python
版本的完整开发流程。 - 现代化的项目管理:原生支持
pyproject.toml
(PEP 517/518/621 标准),这是现代Python
项目事实上的标准配置文件。uv
能清晰地处理依赖分组(例如开发依赖),并生成跨平台的uv.lock
锁定文件。这个锁定文件精确记录了所有直接和间接依赖的具体版本和来源,确保在任何机器、任何时间都能重建完全一致的环境,实现真正的确定性构建。 - 良好的兼容性:
uv
提供了与pip
高度兼容的命令接口 (uv pip ...
),并且能够理解requirements.txt
文件格式,这使得将现有项目迁移到uv
的过程相对平滑。 - 活跃的开发与未来:由
Astral
团队积极维护并快速迭代,采用MIT
开源许可。社区关注度高,发展潜力巨大,未来可期。
使用 uv
,开发者有望体验到类似 Node.js
( npm
/ yarn
/ pnpm
) 或 Rust
( Cargo
) 那样流畅统一的依赖管理工作流。
安装 UV
安装 uv
非常简单。官方推荐使用其提供的安装脚本,因为它不依赖于系统上已有的 Python
环境。当然,通过 pip
或系统包管理器也是可行的选择。
- 推荐方式 (跨平台脚本):
# macOS / Linux (bash, zsh, etc.) curl -LsSf https://astral.sh/uv/install.sh | sh # Windows (PowerShell) powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
注意:官方脚本默认会将
uv
安装到用户目录下的特定位置(例如Linux
/macOS
的~/.uv/bin
或Windows
的%LOCALAPPDATA%\uv\bin
),这通常位于系统盘(如C:
盘)。 - 使用 pip (需要现有 Python 环境):
pip install uv # 或推荐使用 pipx 进行隔离安装 # pipx install uv
如果你的
Python
环境或pipx
环境本身不在系统盘,通过这种方式安装的uv
通常也会跟随它们的位置。你可以通过设置PIPX_HOME
环境变量来控制pipx
的安装路径。 - 使用系统包管理器 (示例):
# macOS (Homebrew) brew install uv # Windows (Scoop) # 可以先将 Scoop 本身安装到非系统盘,然后用它安装 uv scoop install uv # Arch Linux pacman -S uv
如果像
Scoop
这样的包管理器本身被配置在非系统盘,那么它安装的应用(包括uv
)通常也会安装在同一驱动器。 - 使用 Cargo (需要 Rust 环境):
cargo install uv --locked --git https://github.com/astral-sh/uv
uv
会被安装到Cargo
的bin
目录。可以通过设置CARGO_HOME
环境变量将整个.cargo
目录(包含下载的crates
和编译产物)迁移到非系统盘。
安装完成后,运行 uv --version
或 uv help
来验证安装是否成功。
配置 UV 数据存储位置 (进阶)
默认情况下,uv
会将其缓存、下载的 Python
版本以及通过 uv tool install
安装的全局工具存储在用户目录下的默认位置(通常位于系统盘)。如果你希望将这些数据存放到其他驱动器(例如 D:
盘)以节省系统盘空间或减少 SSD
写入,可以通过设置环境变量来实现。
以下是几个关键的环境变量:
UV_CACHE_DIR
: 控制uv
缓存目录的位置。缓存包括下载的包文件、构建的wheel
等,可能占用较大空间。UV_PYTHON_INSTALL_DIR
: 控制通过uv python install
下载和管理的Python
解释器的安装位置。UV_TOOL_INSTALL_DIR
: 控制通过uv tool install
安装的全局Python
工具及其隔离环境的存储位置。
如何设置环境变量 (示例):
假设目标是将所有 uv
数据存储到 D:\uvdata
目录下。
- Windows (PowerShell - 临时设置,仅当前会话有效):
$env:UV_CACHE_DIR = "D:\uvdata\cache" $env:UV_PYTHON_INSTALL_DIR = "D:\uvdata\python" $env:UV_TOOL_INSTALL_DIR = "D:\uvdata\tools" # 之后在此会话中运行 uv 命令,数据将写入新位置 uv pip install requests
- Windows (系统环境变量 - 永久设置):
- 在
Windows
搜索栏查找“环境变量”。 - 点击“编辑系统环境变量”。
- 在“系统属性”对话框中,点击“环境变量...”按钮。
- 在“用户变量”或“系统变量”区域(推荐“用户变量”,除非需要为所有用户设置),点击“新建...”。
- 输入变量名(如
UV_CACHE_DIR
)和变量值(如D:\uvdata\cache
)。 - 为其他两个变量重复此操作。
- 点击“确定”关闭所有对话框。
- 关键: 需要重新打开
PowerShell
或命令提示符窗口,新的环境变量才会生效。
- 在
- Linux / macOS (bash/zsh - 临时设置):
export UV_CACHE_DIR="/path/to/non_system_drive/uvdata/cache" export UV_PYTHON_INSTALL_DIR="/path/to/non_system_drive/uvdata/python" export UV_TOOL_INSTALL_DIR="/path/to/non_system_drive/uvdata/tools" # 之后在此会话中运行 uv 命令 uv pip install requests
- Linux / macOS (永久设置):
将上面的export
命令添加到你的 Shell 配置文件(例如~/.bashrc
,~/.zshrc
,~/.profile
)中,然后执行source ~/.your_config_file
或重启终端使配置生效。
重要提示:
- 设置这些环境变量后,
uv
会自动使用指定的路径。请确保这些目录存在且uv
拥有写入权限。 - 虚拟环境 (
.venv
) 的位置:uv venv
默认在你的项目根目录下创建.venv
文件夹。因此,只要你的项目本身位于非系统盘(比如D:\myproject
),那么.venv
自然也会在该盘。通常无需为.venv
单独配置路径来避开系统盘。当然,你也可以通过uv venv /path/to/custom/env
显式指定虚拟环境的创建位置,但这更多是为了自定义环境路径,而非解决系统盘存储问题。
通过合理配置这些环境变量,可以有效管理 uv
产生的数据,将其引导到空间更充裕或更合适的存储位置。
UV 核心概念
在使用 uv
管理项目时,理解以下几个核心概念非常重要:
pyproject.toml
:现代Python
项目的标准配置文件 (基于 PEP 517/518/621)。uv
利用它来定义项目元数据(名称、版本、描述等)、所需的Python
版本 (requires-python
) 以及项目的主要依赖 (dependencies
) 和可选依赖组(例如dev-dependencies
)。它是项目配置的“单一事实来源”。uv.lock
:由uv
自动生成和管理的锁定文件。它精确记录了项目所有依赖(包括间接依赖)的具体版本号和来源哈希值。其核心价值在于确保环境的可复现性:无论何时何地,只要基于同一个uv.lock
文件安装依赖,就能得到完全相同的包组合。这个文件不应该手动编辑。- 虚拟环境 (
.venv
):uv
极力推荐并简化了虚拟环境的使用。它默认在项目根目录下创建名为.venv
的隔离环境来存放项目依赖。大多数uv
命令(如add
,sync
,run
)都能自动检测并在此环境中执行操作,避免了全局Python
环境的污染。
使用 UV 管理 Python 项目
下面通过一个完整流程,演示如何使用 uv
来创建和管理一个 Python
项目。
初始化项目 (uv init
)
使用 uv init
命令可以快速搭建一个新项目的基本结构。
# 确保在期望的驱动器上操作,例如在 D: 盘
# D:
# mkdir my_uv_project
# cd my_uv_project
# 初始化名为 my_uv_project 的项目
uv init my_uv_project
cd my_uv_project
执行后,uv
会在 my_uv_project
目录下生成:
.git/
和.gitignore
:自动初始化Git
仓库,并提供一个常用的Python
项目.gitignore
文件。.python-version
:记录项目建议或要求的Python
版本(例如3.12
)。uv
会参考此文件来选择或安装合适的Python
解释器。pyproject.toml
:项目的核心配置文件,包含项目名、版本、描述、Python
版本要求和空的dependencies
列表。README.md
:一个空的README
文件。src/my_uv_project/__init__.py
: 一个基本的源代码结构(如果使用src
布局)。或者一个简单的hello.py
示例文件。
# pyproject.toml 示例内容 (可能略有不同)
[project]
name = "my-uv-project"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12" # 根据系统情况或指定版本生成
dependencies = []
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
# uv 可能还会添加 tool.uv 相关配置
创建与同步环境 (uv venv
, uv sync
)
项目初始化后,需要创建虚拟环境并同步依赖状态(即使是空依赖,首次同步也会生成 uv.lock
)。
- 创建虚拟环境 (
uv venv
):
虽然uv sync
等命令在需要时会自动创建.venv
,但也可以显式创建:# 创建默认的 .venv 环境 (uv 会根据 .python-version 或系统查找合适的 Python) # 这个 .venv 会在当前项目目录下创建 uv venv # 创建时指定 Python 版本 uv venv --python 3.11 # 指定自定义环境名称 (不常用,因为 uv 生态默认与 .venv 配合) uv venv my_custom_env
如果需要手动操作环境(例如使用非
uv
管理的工具),则需要激活它:# Linux/macOS source .venv/bin/activate # Windows (PowerShell) .venv\Scripts\Activate.ps1 # Windows (CMD) .venv\Scripts\activate.bat
再次强调:对于绝大多数
uv
命令 (add
,remove
,sync
,run
等),通常不需要手动激活环境,uv
会自动查找并使用.venv
。 - 同步环境 (
uv sync
):
这是核心命令之一,用于确保虚拟环境的状态与pyproject.toml
(通过uv.lock
文件)或requirements.txt
文件精确一致。首次运行时,它会:- 读取
pyproject.toml
的依赖定义。 - 执行依赖解析。
- 生成
uv.lock
文件。 - 在
.venv
中安装所有必需的包(初始阶段可能只有项目本身作为可编辑包)。
# 在项目根目录运行 uv sync
执行后,你会看到
.venv
目录被创建或更新,并且生成了一个uv.lock
文件。 - 读取
管理依赖 (uv add
, uv remove
, uv lock
)
这是 uv
最常用的功能,推荐使用基于 pyproject.toml
的工作流。
- 添加依赖 (
uv add
):
将包添加到pyproject.toml
的[project.dependencies]
部分,并自动安装或更新到.venv
环境中。同时uv.lock
也会被更新。# 添加最新稳定版的 pandas uv add pandas # 添加 requests,并指定版本约束 uv add "requests>=2.20,<3.0" # 添加开发依赖 (如测试框架 pytest),会写入 [tool.uv.dev-dependencies] uv add pytest --dev uv add ruff --dev # 从 Git 仓库添加依赖 uv add git+https://github.com/psf/requests.git # 添加本地路径的包 (以可编辑模式安装) uv add -e ../my_local_library
- 移除依赖 (
uv remove
):
从pyproject.toml
中移除指定的包,并从.venv
环境中卸载它以及不再被需要的下游依赖。# 移除 pandas uv remove pandas # 移除开发依赖 pytest uv remove pytest --dev
- 更新依赖:
- 将所有依赖更新到
pyproject.toml
中约束允许的最新版本,并重新生成uv.lock
:# 1. 更新 lock 文件 uv lock --upgrade # 2. 应用 lock 文件更新到环境 uv sync
- 只更新特定的包到最新版本:
# 方法一:指定包更新 lock 文件,然后同步 uv lock --upgrade-package requests uv sync # 方法二:直接 'add' 最新版 (也会更新 lock 和环境) uv add requests@latest
- 将所有依赖更新到
- 手动编辑
pyproject.toml
后:
如果你直接修改了pyproject.toml
文件中的依赖列表,需要执行以下两步来使更改生效:uv lock
: 根据pyproject.toml
的新内容重新计算依赖并更新uv.lock
文件。uv sync
: 将uv.lock
文件中的状态同步到.venv
虚拟环境。
运行代码与命令 (uv run
)
uv run
是 uv
提供的一个极为便捷的功能。它允许你在 uv
管理的虚拟环境上下文中执行 Python
脚本或任何命令,而无需预先手动激活该环境。这是 uv
简化工作流程的关键特性之一,非常值得掌握。
工作原理:
当你执行 uv run <command> [args...]
时:
- 自动发现环境:
uv
会自动查找当前目录及父目录中的.venv
虚拟环境。 - 内部配置环境执行:
- 对于
uv run python your_script.py
这样的命令,uv
会直接调用.venv
目录下的Python
解释器 (.venv/bin/python
或.venv/Scripts/python.exe
) 来运行脚本。 - 对于
uv run pytest tests/
或uv run ruff format .
这样的命令,uv
会在执行该命令的子进程内部,临时将.venv/bin
(或.venv/Scripts
) 目录添加到系统PATH
环境变量的最前面。这样,即使你没有激活环境,操作系统也能找到并执行安装在虚拟环境中的命令行工具(如pytest
,ruff
)。
- 对于
如何运行 Python 文件?
要运行项目中的 Python
文件(例如 src/my_package/main.py
或根目录的 app.py
),推荐这样做:
uv run python src/my_package/main.py
# 或者
uv run python app.py
优势:
- 无需手动激活:省去了输入
source .venv/bin/activate
或.venv\Scripts\Activate.ps1
的麻烦,极大简化了日常开发和脚本执行。 - 环境一致性保证:确保你的代码和工具总是在项目配置的正确虚拟环境中运行。
- 简化 CI/CD 脚本:在自动化流程(如
GitHub Actions
,GitLab CI
)中,可以直接使用uv run
执行测试、构建、部署等任务,无需处理复杂的环境激活逻辑。
更多 uv run
示例:
# 运行安装在环境中的 pytest 测试
uv run pytest tests/
# 运行安装在环境中的 ruff 代码格式化
uv run ruff format .
# 运行任意系统命令,uv 会确保 .venv/bin 在 PATH 中
uv run alembic upgrade head
# 向脚本传递参数
uv run python your_script.py --input data.csv --output results.json
何时仍需手动激活?
手动激活 (source activate
或类似命令) 的场景大大减少了。可能主要是在同一个 Shell 会话中,你需要:
- 频繁地交互式运行多个依赖于虚拟环境的命令(例如,直接输入
python
进入解释器,然后是pytest
,再是ruff
)。 - 使用某些依赖于激活脚本设置的特定环境变量(除了
PATH
之外)的非Python
工具。
但对于大多数日常开发任务,uv run
提供的自动环境管理更加方便高效。
使用 requirements.txt
(兼容工作流)
虽然 uv
推荐使用 pyproject.toml
,但它也完全支持传统的 requirements.txt
工作流,并提供了 pip
兼容的命令接口,而且速度更快。
- 安装依赖 (
uv pip install
):# 安装单个包 uv pip install flask # 从 requirements 文件安装 uv pip install -r requirements.txt # 可以同时指定多个文件 uv pip install -r requirements.txt -r requirements-dev.txt # 安装当前项目 (以可编辑模式) uv pip install -e .
- 卸载依赖 (
uv pip uninstall
):uv pip uninstall flask # 从文件批量卸载 uv pip uninstall -r requirements-to-remove.txt
- 生成依赖列表 (
uv pip freeze
):# 输出当前环境安装的所有包 (类似 pip freeze) uv pip freeze > requirements.lock.txt # 常用于生成锁定文件
- 编译依赖 (
uv pip compile
) (推荐的requirements
工作流):
这种方式类似pip-tools
。你维护一个requirements.in
文件(只包含直接依赖),然后用uv
生成包含所有间接依赖和精确版本的requirements.txt
锁定文件。# requirements.in 内容示例: # flask # requests>=2.25 # 生成 requirements.txt uv pip compile requirements.in -o requirements.txt # 为开发环境编译 (假设有 requirements-dev.in) # uv pip compile requirements-dev.in -o requirements-dev.txt
- 同步环境 (
uv pip sync
):
根据一个或多个requirements.txt
文件的内容,精确同步虚拟环境:安装缺失的包,移除多余的包。# 同步主依赖和开发依赖 uv pip sync requirements.txt requirements-dev.txt
- 查看已安装包 (
uv pip list
,uv pip show
,uv pip tree
):uv pip list # 列出已安装的包和版本 uv pip show flask # 显示 flask 包的详细信息 uv pip tree # 以树状结构显示依赖关系
管理 Python 版本 (uv python
)
uv
内建了下载、管理和选用 Python
版本的功能,类似于 pyenv
。(记得可以通过 UV_PYTHON_INSTALL_DIR
环境变量配置这些 Python
的安装位置)
- 列出可用和已安装版本 (
uv python list
):# 列出已安装和当前使用的版本 uv python list # 显示所有可供下载的补丁版本 # uv python list --all-versions # 只显示已安装的版本 uv python list --only-installed
- 安装 Python 版本 (
uv python install
):# 安装最新的稳定版 (如果尚未安装) uv python install # 安装特定版本 uv python install 3.11.5 # 安装 3.10 系列的最新可用版 uv python install 3.10
uv
会将下载的Python
安装到其管理的目录中 (uv python dir
可查看该路径,受UV_PYTHON_INSTALL_DIR
影响)。 - 卸载 Python 版本 (
uv python uninstall
):uv python uninstall 3.10.8 # 卸载 3.11 系列所有已安装版本 uv python uninstall 3.11
- 固定项目 Python 版本 (
uv python pin
):
在当前目录创建或更新.python-version
文件,声明项目应使用的Python
版本。uv python pin 3.11
之后
uv venv
,uv run
,uv sync
等命令会优先查找并使用这个版本。 - 查找 Python 解释器 (
uv python find
):# 查找匹配 3.12 的 Python 解释器路径 uv python find 3.12
管理全局工具 (uv tool
)
uv
可以像 pipx
一样,安装和运行全局 Python CLI
工具,并将每个工具隔离在独立的环境中,避免依赖冲突。(同样,工具的存储位置可通过 UV_TOOL_INSTALL_DIR
环境变量配置)
- 运行工具 (临时执行,
uv tool run
或uvx
):
临时下载(如果需要)并执行工具,执行完毕后不保留。这对于一次性使用的工具非常方便。uvx
是uv tool run
的简写形式。# 运行 ruff 检查当前目录,临时下载 ruff uv tool run ruff check . # 使用简写 uvx uvx ruff check . # 如果命令名 (http) 和包名 (httpie) 不同,使用 --from uvx --from httpie http https://example.com
- 安装全局工具 (
uv tool install
):
将工具及其依赖安装到uv
管理的独立环境中,并将其可执行文件链接到用户路径(可能需要重启终端或手动配置PATH
才能直接调用)。这类似于pipx install
。uv tool install black uv tool install httpie
安装后,理论上可以在任何地方直接运行
black .
或http https://example.com
。 - 列出已安装工具 (
uv tool list
):uv tool list
- 升级工具 (
uv tool upgrade
):uv tool upgrade black # 升级所有已安装工具 # uv tool upgrade --all
- 卸载工具 (
uv tool uninstall
):uv tool uninstall black
- 查看工具安装目录 (
uv tool dir
):
显示uv
存放全局工具及其环境的根路径 (受UV_TOOL_INSTALL_DIR
影响)。
管理缓存 (uv cache
)
uv
使用全局缓存来加速包的下载和构建过程。(缓存位置可通过 UV_CACHE_DIR
环境变量配置)
- 清理缓存 (
uv cache clean
):
删除所有uv
缓存内容。这可以用于解决潜在的缓存污染问题或释放磁盘空间。uv cache clean
- 显示缓存目录 (
uv cache dir
):
查看当前uv
缓存文件的存储位置 (受UV_CACHE_DIR
影响)。
单脚本项目管理
对于一些简单的小工具或脚本,uv
支持一种非常轻量级的管理方式:将项目元数据和依赖直接嵌入 Python
脚本头部的特殊注释块中。
- 初始化脚本 (
uv init --script
):# 创建一个名为 my_script.py 的脚本,并指定 Python 版本要求 uv init --script my_script.py --python ">=3.10"
这会在
my_script.py
文件开头生成类似以下的注释块:#!/usr/bin/env python # /// script # requires-python = ">=3.10" # dependencies = [ # ] # /// import sys def main() -> None: print(f"Hello from {sys.argv[0]}!") if __name__ == "__main__": main()
- 添加/移除脚本依赖 (
uv add/remove --script
):
可以直接使用add
或remove
命令,配合--script
参数来修改脚本头部的依赖列表。# 为 my_script.py 添加 requests 依赖 uv add --script my_script.py requests # 从 my_script.py 移除 requests 依赖 uv remove --script my_script.py requests
这些命令会直接修改脚本文件头部的
dependencies
列表。 - 运行脚本 (
uv run
):
直接使用uv run
即可执行该脚本。uv run my_script.py
uv
会自动读取脚本头部的元数据,按需创建临时的虚拟环境,安装其中声明的依赖,然后执行脚本。这种方式非常适合分发单个、自包含的Python
工具脚本。
未来展望与建议
uv
无疑是一个雄心勃勃且发展极其迅速的项目。它借助 Rust
带来的性能优势和精心设计的统一接口,有望显著改善 Python
开发者的包与环境管理体验。其核心价值在于速度和整合。
尽管 uv
相对年轻,生态系统(如 IDE 深度集成、第三方教程资源)仍在快速成长中,并且由于其活跃的迭代,命令或行为可能在版本间有细微调整(建议关注其更新日志)。
但就目前而言,uv
的核心功能已经相当稳定和强大。
建议:
- 对于新启动的
Python
项目,强烈推荐直接采用uv
。它能从一开始就带来清爽、高效的管理体验。 - 对于那些饱受现有工具链(如
pip
+virtualenv
+pip-tools
组合)复杂性或性能问题困扰的开发者和团队,uv
是一个非常有吸引力的替代方案,值得投入时间进行评估和迁移尝试。 - 对于已经深度使用
Poetry
或PDM
并依赖其特定高级功能(例如复杂的插件系统、精细的发布流程管理)的成熟项目,迁移可能需要更仔细的评估,权衡uv
带来的速度和简洁性与可能失去的特定功能。
uv
正在快速成为 Python
开发工作流中一个不可忽视的力量,它的出现可能会像 ruff
一样,在 Python
社区引发新一轮的工具革新。它的未来值得我们持续关注。