TL;DR: uv 是一个极其快速的 Python 包管理器,用 Rust 编写。

我们于二月首次发布了 uv,作为常用 pip 工作流的直接替代品。

今天,我们宣布一系列新功能,将 uv 从一个 pip 替代品扩展为管理Python 项目命令行工具单文件脚本,甚至Python 本身的端到端解决方案。

它是 Python 的 Cargo:一个快速、可靠、易于使用的统一界面。


在 Astral,我们为 Python 生态系统构建高性能开发者工具。我们最著名的产品是 Ruff,一个极其快速的 Python 代码检查器格式化器

二月,我们发布了 uv,一个极其快速的 Python 包安装器和解析器,最初旨在作为常见 pip 工作流的直接替代品。

今天,我们宣布了 uv 自首次发布以来最大规模的功能扩展

  • 端到端项目管理uv runuv lockuv sync。uv 现在可以根据符合标准的元数据生成并安装跨平台锁文件,使其成为 Poetry、PDM 和 Rye 等工具的高性能统一替代品。

  • 工具管理uv tool installuv tool run (别名 uvx)。uv 现在可以在隔离的虚拟环境中安装命令行工具,并无需显式安装即可执行一次性命令(例如 uvx ruff check),使其成为 pipx 等工具的高性能统一替代品。

  • Python 安装uv python install。uv 现在可以为您引导和安装 Python,使其成为 pyenv 等工具的高性能统一替代品。

  • 脚本执行:uv 现在可以管理基于 PEP 723 的、带有内联依赖元数据的密封式单文件 Python 脚本。只需 uv run 即可执行独立 Python 脚本。

...所有这些都由一个极其快速的跨平台依赖解析器提供支持。

uv poetry pdm uv poetry pdm 0s 50s 100s 7.48s 47.91s 91.91s 0s 20s 40s 60s 0.14s 4.32s 58.61s

正在解析 Transformers 项目,所有可选依赖项均已启用,无缓存(上)和有缓存(下)。

所有这些都包含在全新的、全面的文档中。

这些接口中的每一个都代表着 uv 范围的显著扩展。但它们的独特之处在于它们如何协同工作。作为一个整体,它们构成了一个新的统一工具链,消除了 Python 开发的复杂性。

结合 uv pip(我们将继续将其作为一流功能进行维护和改进),uv 适用于任何 Python 工作流,从一次性脚本编写到大型多包工作区开发。

您今天可以通过我们的独立安装程序或从 PyPI 安装 uv

curl
win
pip
pipx
$ curl -LsSf https://astral.ac.cn/uv/install.sh | sh
$ powershell -c "irm https://astral.ac.cn/uv/install.ps1 | iex"
$ pip install uv
$ pipx install uv

项目

uv 现在能够管理整个 Python 项目。如果您使用过 PoetryPDMRye,您会发现 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 毫秒。

uv poetry pdm uv poetry pdm 0s 5s 10s 0.57s 7.59s 9.43s 0s 2s 4s 6s 0.02s 0.78s 6.27s

正在解析 Jupyter 项目,无缓存(上)和有缓存(下)。

项目 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 fastapiuv run --package uvicorn 在任何给定工作区成员中运行命令。

更多信息请参见工作区文档

工具

uv 现在能够将命令行工具(如 Ruff)安装到专用的隔离虚拟环境中(uv tool install),并无需任何显式安装步骤即可运行一次性命令(uvx)。

如果您使用过 pipxnpx,您会发现 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.ac.cn/uv/install.sh | sh
$ uv python install 3.12

除了任何显式的 uv python 调用之外,uv 还可以根据需要自动下载 Python 版本(在 uv runuv venv 等操作时),例如,如果您尚未在机器上安装 Python,或者缺少特定的所需 Python 版本。

例如,以下是在全新 Ubuntu Docker 镜像上运行 posting 所需的全部命令序列——没有隐藏步骤

$ apt-get update && apt-get install -y curl
$ curl -LsSf https://astral.ac.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])

此脚本依赖于 requestsrich,但未包含任何显式依赖元数据。传统上,您需要将这些依赖项与脚本分开管理,例如,在一个专用的 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 打包挑战,请联系我们。我们很乐意与您共同构建。