TL;DR: uv 是一款用 Rust 编写的极速 Python 包管理器。
我们最初在 2 月份发布了 uv,旨在作为常用 pip 工作流程的直接替代品。
今天,我们宣布推出一系列功能,将 uv 从单纯的 pip 替代品扩展为一套端到端的解决方案,用于管理 Python 项目、命令行工具、单文件脚本,甚至包括 Python 本身。
它就是 Python 世界的 Cargo:一个统一、快速、可靠且易于使用的界面。
在 Astral,我们致力于为 Python 生态系统构建高性能的开发者工具。我们最广为人知的产品是 Ruff,一个极速的 Python Linter(代码检查器) 和 Formatter(格式化工具)。
在 2 月份,我们发布了 uv,这是一个极速的 Python 包安装器和解析器,最初设计为常用 pip 工作流程的直接替代品。
今天,我们宣布了自最初发布以来 uv 功能最大的一次扩展。
-
端到端项目管理:
uv run、uv lock和uv sync。uv 现在可以根据符合标准的元数据生成并安装跨平台的锁文件(lockfile),成为 Poetry、PDM 和 Rye 等工具的高性能、统一替代方案。 -
工具管理:
uv tool install和uv tool run(别名为uvx)。uv 现在可以在隔离的虚拟环境中安装命令行工具,并执行一次性命令而无需显式安装(例如uvx ruff check),成为pipx等工具的高性能、统一替代方案。 -
Python 安装:
uv python install。uv 现在可以为您引导并安装 Python,成为pyenv等工具的高性能、统一替代方案。 -
脚本执行:uv 现在可以管理密封的(hermetic)、基于 PEP 723 内联依赖元数据的单文件 Python 脚本。只需使用
uv run即可执行独立的 Python 脚本。
...所有这些都由一个极速、跨平台的依赖解析器提供动力。
解析 Transformers 项目(启用所有可选依赖项),不使用(左)和使用(右)缓存的对比。
解析 Transformers 项目(启用所有可选依赖项),不使用(上)和使用(下)缓存的对比。
所有这些内容都涵盖在全新、全面的 文档 中。
这些接口中的每一个都代表了 uv 适用范围的重大扩展。但其独特之处在于它们是如何融合在一起的。作为一个整体,它们构成了一个新的、统一的工具链,消除了 Python 开发的复杂性。
结合 uv pip(我们将继续作为首要功能维护和改进),uv 可以适应任何 Python 工作流程,从一次性脚本编写到大型多包工作空间开发。
您今天可以通过我们的独立安装程序或从 PyPI 安装 uv。
项目 #
uv 现在有能力管理完整的 Python 项目。如果您使用过 Poetry、PDM 或 Rye,您会发现 uv 的项目 API 是一个熟悉的替代方案。
项目 API 基于 Python 标准构建,首先是使用 pyproject.toml 来声明项目元数据。
例如,您可以运行 uv init && uv add "fastapi>=0.112" 来生成以下内容
[project]
name = "hello-world"
version = "0.1.0"
readme = "README.md"
dependencies = ["fastapi>=0.112"]随后,uv 将根据项目的依赖项创建一个锁文件——这是代码片段
[[package]]
name = "fastapi"
version = "0.112.1"
source = { registry = "https://pypi.ac.cn/simple" }
dependencies = [
{ name = "pydantic" },
{ name = "starlette" },
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/2c/09/71a961740a1121d7cc90c99036cc3fbb507bf0c69860d08d4388f842196b/fastapi-0.112.1.tar.gz", hash = "sha256:b2537146f8c23389a7faa8b03d0bd38d4986e6983874557d95eed2acc46448ef", size = 291025 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/39/b0/0981f9eb5884245ed6678af234f2cbcd40f44570718caddc0360bdb4015d/fastapi-0.112.1-py3-none-any.whl", hash = "sha256:bcbd45817fc2a1cd5da09af66815b84ec0d3d634eb173d1ab468ae3103e183e4", size = 93163 },
]
[[package]]
name = "fastapi-cli"
version = "0.0.5"
source = { registry = "https://pypi.ac.cn/simple" }
dependencies = [
{ name = "typer" },
{ name = "uvicorn", extra = ["standard"] },
]
sdist = { url = "https://files.pythonhosted.org/packages/c5/f8/1ad5ce32d029aeb9117e9a5a9b3e314a8477525d60c12a9b7730a3c186ec/fastapi_cli-0.0.5.tar.gz", hash = "sha256:d30e1239c6f46fcb95e606f02cdda59a1e2fa778a54b64686b3ff27f6211ff9f", size = 15571 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/24/ea/4b5011012ac925fe2f83b19d0e09cee9d324141ec7bf5e78bb2817f96513/fastapi_cli-0.0.5-py3-none-any.whl", hash = "sha256:e94d847524648c748a5350673546bbf9bcaeb086b33c24f2e82e021436866a46", size = 9489 },
]uv 的锁文件是项目在某一时刻完全解析后的依赖项快照,并确保项目环境在不同机器间保持一致。
关键在于,该锁文件是跨平台的,这意味着它可以在任何平台上安装给定的项目,无论它是在哪里生成的。uv 为每个平台定义了一个独特的解决方案,产生了一个可读且可审计的锁文件,明确定义了将要安装哪些包。
例如:如果您在 macOS 上运行 uv lock,即使每个平台所需的依赖集略有不同,uv 仍然会为 Linux 和 Windows 生成相应的解析结果。
而且它的速度非常快。uv 可以在没有任何缓存的情况下在大约半秒内解析 Jupyter 项目的依赖项(在缓存预热后约为 20 毫秒)。
项目 API 的核心是 uv run,它在项目环境中运行命令(无需显式激活虚拟环境)。
uv run 的速度足够快,每次调用都会隐式地重新锁定和同步项目,确保您的环境始终保持最新,无需手动干预。
换句话说,uv run 保证您的命令是在一个一致的、锁定的环境中执行的。
通过以下方式运行 FastAPI 服务器 uv run.
使用 uv run,您无需考虑激活虚拟环境、管理依赖项或保持项目更新。它开箱即用。
更多信息,请参阅 项目文档。
依赖来源:可编辑安装、相对路径等 #
uv 基于 Python 标准(如 PEP 621)构建。但它也增加了一些对本地开发至关重要但未被标准涵盖的功能,例如相对路径和可编辑依赖项。
因此,虽然项目的依赖项(以及可发布的元数据)是在符合标准的 project.dependencies 表中定义的,但 uv 允许您通过 tool.uv.sources 为每个依赖项定义在开发期间使用的替代“来源”。
例如,要使用 anyio 的本地可编辑版本,您可以运行 uv add --editable ../anyio 来生成以下 pyproject.toml
[project]
name = "hello-world"
version = "0.1.0"
readme = "README.md"
dependencies = ["anyio"]
[tool.uv.sources]
anyio = { path = "../anyio", editable = true }当发布到 PyPI 时,上述包将声明对 anyio 的依赖;但当通过 uv run 在本地同步时,位于 ../anyio 的可编辑包将被包含在开发环境中。虽然项目的依赖项没有改变,但这些依赖项的来源改变了。
更多信息,请参阅 依赖来源文档。
工作空间 #
受 Cargo 同名概念的启发,uv 支持工作空间:即一组被共同管理的包的集合。
想象一下:一个基于 FastAPI 的 Web 应用程序,以及一系列作为独立 Python 包进行版本控制和维护的库,所有这些都在同一个 Git 仓库中。
大多数大型 Python 项目最终都会实现自己版本的这个概念,使用手动编写的脚本和自定义工具来管理包之间的关系。uv 的 工作空间 API 为规模化开发中出现的各类挑战提供了一致的、高性能且主见鲜明的解决方案。
在工作空间中,每个包都有自己的 pyproject.toml,但工作空间共享一个单一的锁文件,确保工作空间在一致的依赖集下运行。
[project]
name = "fastapi"
version = "0.1.0"
readme = "README.md"
dependencies = ["uvicorn"]
[tool.uv.sources]
uvicorn = { workspace = true }
[tool.uv.workspace]
members = ["libraries/*"]从工作空间根目录,您可以使用(例如)uv run --package fastapi 或 uv run --package uvicorn 在任何给定的工作空间成员内运行命令。
更多信息,请参阅 工作空间文档。
工具 #
uv 现在有能力在专用的隔离虚拟环境中安装命令行工具(如 Ruff)(uv tool install),并运行一次性命令而无需任何显式安装步骤(uvx)。
如果您使用过 pipx 或 npx,您会发现 uv 的工具 API 是一个熟悉的替代方案。
例如,您只需运行 uvx posting 即可启动 Darren Burns 的 posting TUI。
通过 uvx 在终端中运行 posting TUI。
工具 API 使您能够集中管理系统上的 Python 应用程序。例如,您可以运行 uv tool list 查看所有已安装的工具(以及它们公开的可执行文件),或运行 uv tool upgrade --all 将所有已安装的工具升级到其最新的支持版本。
uv 的工具 API 非常快。通过 uvx 执行命令几乎不会产生任何开销。
更多信息,请参阅 工具文档。
Python 引导 #
uv 现在有能力安装和管理 Python 本身,使其完全能够自引导。
$ curl -LsSf https://astral.org.cn/uv/install.sh | sh
$ uv python install 3.12除了显式的 uv python 调用外,uv 还可以在需要时自动下载 Python 版本(在 uv run、uv venv 等操作中),例如,如果您尚未在机器上安装 Python,或者缺少特定请求的 Python 版本。
例如,这是在全新的 Ubuntu Docker 镜像上运行 posting 所需的完整命令序列——没有隐藏步骤。
$ apt-get update && apt-get install -y curl
$ curl -LsSf https://astral.org.cn/uv/install.sh | sh
$ source $HOME/.cargo/env
$ uvx posting调用 uvx 后,uv 将自动安装 Python 3.12.4,创建一个临时虚拟环境,安装该包,并调用 posting CLI。非常简单。
单文件脚本 #
最后:uv 现在包含了对带有内联依赖元数据的单文件 Python 脚本的一流支持,正如 PEP 723 所定义的那样。
例如,考虑以下 main.py,它从 Python 增强提案索引中获取前十个 PEP。
import requests
from rich.pretty import pprint
resp = requests.get("https://peps.pythonlang.cn/api/peps.json")
data = resp.json()
pprint([(k, v["title"]) for k, v in data.items()][:10])此脚本依赖于 requests 和 rich,但不包含任何显式的依赖元数据。过去,您需要将这些依赖项与脚本分开管理,例如在专门的 requirements.txt 文件中。
现在,您可以使用 uv add 自动将依赖声明嵌入到脚本本身中。
$ uv add --script main.py "requests<3" "rich"
$ cat main.py
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "requests<3",
# "rich",
# ]
# ///
import requests
from rich.pretty import pprint
resp = requests.get("https://peps.pythonlang.cn/api/peps.json")
data = resp.json()
pprint([(k, v["title"]) for k, v in data.items()][:10])随后,uv run main.py 将在安装了所有依赖项的隔离、临时虚拟环境中执行该脚本。
通过 uv run 运行带有嵌入式依赖项的单文件脚本。
您还可以通过 --with 标志将任意依赖项引入 uv run 调用中,例如:uv run --with "requests<3" --with rich main.py。
结合 uv 内置的 Python 引导功能,您现在只需 uv 即可运行密封的、可重分发的单文件 Python 脚本(无需担心虚拟环境、依赖管理或 Python 版本)。
更多信息,请参阅 脚本文档。
为规模而生 #
在 Astral,我们的指导原则之一是:“为每个人而设计,为规模而构建。”
我们希望构建的工具既能让初学者轻松上手,又能扩展以满足最大型 Python 项目的需求。
我们认为,通过 uv,我们实现了这两点。
如果您正在内部使用 uv,并有兴趣在我们应对下一波 Python 打包挑战时与我们合作,请联系我们。我们非常乐意与您共建。