uv - Guides 指南 [官方文档翻译]
文章目录
- Guides 指南概述
- 安装 Python
- 入门
- 安装特定版本
- 重新安装 Python
- 查看 Python 安装
- 自动 Python 下载
- 使用现有的 Python 版本
- 运行脚本
- 在没有依赖的情况下运行脚本
- 运行带有依赖的脚本
- 创建一个Python脚本
- 声明脚本依赖
- 使用替代包索引
- 锁定依赖
- 提高可重复性
- 使用不同的 Python 版本
- 使用GUI脚本
- 下一步
- 构建和发布包
- 为打包准备你的项目
- 构建您的包
- 发布您的包
- 安装您的包
- 集成指南
- 在Docker中使用uv
- 入门
- 可用镜像
- 安装uv
- 安装项目
- 使用环境
- 使用已安装的工具
- 在musl-based镜像中安装Python
- 在容器中开发
- 使用 `docker run` 挂载项目
- 使用 `docker compose` 配置 `watch`
- 优化
- 编译字节码
- 缓存
- 中级层
- 不可编辑的安装
- 使用 uv 临时
- 使用pip接口
- 安装一个包
- 安装依赖项
- 安装项目
- 验证图像来源
- 使用uv与Jupyter
- 在项目中使用Jupyter
- 创建内核
- 在没有内核的情况下安装软件包
- 使用 Jupyter 作为独立工具
- 使用 Jupyter 非项目环境
- 使用 VS Code 中的 Jupyter
- 在 GitHub Actions 中使用 uv
- 安装
- 设置 Python
- 多个 Python 版本
- 同步和运行
- 缓存
- 使用 `uv pip`
- 使用 uv 在 GitLab CI/CD 中
- 使用 uv 镜像
- 缓存
- 使用 `uv pip`
- 在 pre-commit 使用 uv
- 使用 uv 与 PyTorch
- 安装 PyTorch
- 使用 PyTorch 索引
- 使用环境标记配置加速器
- 使用可选依赖配置加速器
- The `uv pip` interface
- 自动后端选择
- 使用 uv 与 FastAPI
- 迁移现有的 FastAPI 项目
- 部署
- 使用替代包索引
- Azure Artifacts
- 使用 Azure 访问令牌进行身份验证
- 使用 `keyring` 和 `artifacts-keyring` 进行认证
- 将包发布到 Azure Artifacts
- GoogleArtifactRegistry
- 使用 Google 访问令牌进行身份验证
- 使用 `keyring` 和 `keyrings.google-artifactregistry-auth` 进行认证
- 将包发布到 Google Artifact Registry
- AWS CodeArtifact
- 使用 AWS 访问令牌进行认证
- 使用 `keyring` 和 `keyrings.codeartifact` 进行认证
- 将软件包发布到 AWS CodeArtifact
- 依赖项机器人
- Renovate
- `uv.lock` 输出
- 内联脚本元数据
- 使用 uv 与 AWS Lambda
- 入门
- 部署 Docker 镜像
- 工作区支持
- 部署 zip 存档
- 使用 Lambda 层
Guides 指南概述
https://docs.astral.sh/uv/guides/
查看以下核心指南之一以开始使用:
- 安装 Python 版本
- 运行脚本和声明依赖
- 以工具运行和安装应用程序
- 创建和进行项目
- 构建和发布软件包
- 整合 uv 与其他软件,例如 Docker, GitHub, PyTorch 以及更多
或者,探索概念文档以获取每个概念的全面解析特性。
2025年2月5日
安装 Python
如果您的系统上已经安装了Python,uv将检测并使用它而无需配置。
但是,uv也可以安装和管理Python版本。
uv会根据需要自动安装缺少的Python版本——您不需要安装Python即可开始。
入门
要安装最新版本的 Python:
uv python install
注意:Python 不发布官方的可分发二进制文件。
因此,uv 使用 Astral 的 python-build-standalone
项目的分发版。
有关更多详细信息,请参阅 Python distributions 文档。
一旦安装了 Python,它将被 uv
命令自动使用。
重要:当 Python 通过 uv 安装时,它将不会全局可用(即通过 python
命令)。
此功能支持处于 预览 状态。查看安装 Python 可执行文件 关于详情,请参阅。
您仍然可以使用 uv run
创建并激活一个虚拟环境
安装特定版本
要安装特定的Python版本:
uv python install 3.12
要安装多个Python版本:
uv python install 3.11 3.12
要安装一个替代的 Python 实现,例如 PyPy:
uv python install [[email protected]](/cdn-cgi/l/email-protection)
关于更多细节,请查看python install
文档。
重新安装 Python
要重新安装 uv-managed Python 版本,使用 --reinstall
,例如:
uv python install --reinstall
这将会重新安装 之前安装的所有Python版本。改进一直添加到 Python 发行版中,因此即使 Python 版本没有变化,重新安装也可能解决错误。
查看 Python 安装
要查看可用的和已安装的 Python 版本:
uv python list
更多详情查看 python list
文档。
自动 Python 下载
Python 不需要显式安装即可使用 uv。默认情况下,uv 将自动在需要时下载 Python 版本。例如, 如果未安装,以下内容将下载 Python 3.12:
uvx [[email protected]](/cdn-cgi/l/email-protection) -c "print('hello world')"
即使没有请求特定的 Python 版本,uv 也会在需要时下载最新版本。
例如,如果您的系统上没有 Python 版本,以下内容将 在创建新的虚拟环境之前 安装 Python:
uv venv
提示:如果你想要对何时下载 Python 有更多控制,可以轻松禁用自动下载Python。
使用现有的 Python 版本
uv将使用您系统上 现有的Python安装。此行为不需要配置:如果uv满足命令调用的要求,它将使用系统Python。请参阅 Python发现 文档以获取详细信息。
要强制uv使用Python系统,请提供 --no-managed-python
标志。查看Python版本偏好 文档以获取更多详细信息。
2025年1月30日
运行脚本
一个 Python 脚本是一个用于独立执行的文件,例如,使用 python <script>.py
。
使用uv执行脚本 可确保在 不手动管理环境的情况下 管理脚本依赖关系。
如果你不熟悉Python环境:每个Python安装都有一个可以安装包的环境。通常,创建虚拟环境建议 隔离每个脚本所需的包。
uv会自动为您管理虚拟环境,并更喜欢 declarative 方法来处理依赖关系。
在没有依赖的情况下运行脚本
如果您的脚本没有依赖项,您可以使用 uv run
来执行它:
example.py
print("Hello world")
uv run example.py
Hello world
同样,如果你的脚本依赖于标准库中的模块,就没有更多的事情要做:
example.py
import osprint(os.path.expanduser("~"))
uv run example.py
/Users/astral
脚本可以提供以下参数:
example.py
import sysprint(" ".join(sys.argv[1:]))
$ uv run example.py test
test$ uv run example.py hello world!
hello world!
另外,您的脚本可以直接从stdin读取:
echo 'print("hello world!")' | uv run -
或者,如果你的shell支持here-documents:
uv run - <<EOF
print("hello world!")
EOF
请注意,如果您在一个 项目 中使用 uv run
,即一个包含 pyproject.toml
文件的目录,它将在运行脚本之前安装当前项目。
如果你的脚本不依赖于以下内容:
# 安装脚本所需的依赖
npm install
项目,使用 --no-project
标志跳过:
# Note: the `--no-project` flag must be provided _before_ the script name.
$ uv run --no-project example.py
查看项目指南以获取更多关于在项目中工作的详细信息。
运行带有依赖的脚本
当你的脚本需要其他包时,它们必须安装到脚本运行的环境中。
uv更喜欢按需创建这些环境,而不是使用具有手动管理依赖关系的长期虚拟环境。
这需要明确声明脚本所需的依赖关系。通常,建议使用项目或 内联元数据 inline metadata 来声明依赖关系,但uv也支持每次调用请求依赖关系。
例如,以下脚本需要 rich
。
example.py
import time
from rich.progress import trackfor i in track(range(20), description="For example:"):time.sleep(0.05)
如果未指定依赖项执行此脚本,它将失败:
uv run --no-project example.py
Traceback (most recent call last):File "/Users/astral/example.py", line 2, in <module>from rich.progress import track
ModuleNotFoundError: No module named 'rich'
请求依赖项,使用 --with
选项:
uv run --with rich example.py
For example: ━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:01
如果需要特定版本,可以添加约束到请求的依赖项中:
uv run --with 'rich>12,<13' example.py
可以通过重复使用 --with
选项来请求多个依赖。
注意,如果在 项目 中使用 uv run
,这些依赖项将被包括 在内。
项目的依赖项。要取消此行为,请使用 --no-project
标志。
创建一个Python脚本
Python 最近添加了一个标准格式用于
内联脚本元数据
它允许选择 Python 版本并定义依赖项。使用 uv init --script
来
初始化脚本时使用内联元数据:
uv init --script example.py --python 3.12
声明脚本依赖
内联元数据格式 允许在脚本本身中声明脚本的依赖关系。
uv 支持为您添加和更新内联脚本元数据。使用 uv add --script
来声明脚本。
依赖关系脚本:
uv add --script example.py 'requests<3' 'rich'
这将在脚本顶部添加一个 script
部分,用于声明依赖项,使用 TOML:
example.py
# /// script
# dependencies = [
# "requests<3",
# "rich",
# ]
# ///import requests
from rich.pretty import pprintresp = requests.get("https://peps.python.org/api/peps.json")
data = resp.json()
pprint([(k, v["title"]) for k, v in data.items()][:10])
uv 将自动创建一个包含运行脚本所需依赖的环境,例如:
uv run example.py
[
│ ('1', 'PEP Purpose and Guidelines'),
│ ('2', 'Procedure for Adding New Modules'),
│ ('3', 'Guidelines for Handling Bug Reports'),
│ ('4', 'Deprecation of Standard Modules'),
│ ('5', 'Guidelines for Language Evolution'),
│ ('6', 'Bug Fix Releases'),
│ ('7', 'Style Guide for C Code'),
│ ('8', 'Style Guide for Python Code'),
│ ('9', 'Sample Plaintext PEP Template'),
│ ('10', 'Voting Guidelines')]
重要:当使用内联脚本元数据时,即使使用了 uv run
在 项目 中,项目的依赖也会被忽略。不需要使用 --no-project
标志。
uv 也尊重 Python 版本要求:
example.py
# /// script
# requires-python = ">=3.12"
# dependencies = []
# ///# Use some syntax added in Python 3.12
type Point = tuple[float, float]
print(Point)
注意:即使为空,也必须提供 dependencies
字段。
uv run
将会搜索并使用所需的 Python 版本。Python 版本将会下载如果它
未安装 —— 请参阅关于 Python 版本 的文档
更多详情。
使用替代包索引
如果你希望使用一个替代的 软件包索引 来解析
依赖项,您可以使用 --index
选项提供索引:
uv add --index "https://example.com/simple" --script example.py 'requests<3' 'rich'
这将包括包数据在内联元数据中:
# [[tool.uv.index]]
# url = "https://example.com/simple"
如果您需要通过身份验证才能访问包索引,请参阅以下文档:
包索引
锁定依赖
uv支持使用uv.lock
文件格式锁定PEP 723脚本的依赖项。与使用
项目、脚本必须使用 uv lock
明确锁定。
uv lock --script example.py
运行 uv lock --script
将会在脚本旁边创建一个 .lock
文件(例如,
example.py.lock
)
一旦锁定,后续操作如 uv run --script
、uv add --script
、uv export --script
、
并且 uv tree --script
将会重用锁定的依赖,如果需要的话,更新锁文件。
如果不存在这样的锁文件,像 uv export --script
这样的命令仍然会按预期工作。
但是不会创建一个锁文件。
提高可重复性
除了锁定依赖项之外,uv 还在 tool.uv
部分支持一个 exclude-newer
字段
关于内联脚本元数据以限制 uv 只考虑在特定时间之前发布的分布
日期。这在稍后运行脚本时提高脚本的再现性非常有用。
time.
日期必须指定为 RFC 3339 时间戳
(e.g., 2006-12-02T02:07:43Z
).example.py
# /// script
# dependencies = [
# "requests",
# ]
# [tool.uv]
# exclude-newer = "2023-10-16T00:00:00Z"
# ///import requestsprint(requests.__version__)
使用不同的 Python 版本
uv 允许在每次脚本调用时请求任意的 Python 版本,例如:
example.py
import sysprint(".".join(map(str, sys.version_info[:3])))
$ # Use the default Python version, may differ on your machine
$ uv run example.py
3.12.6
$ # Use a specific Python version
$ uv run --python 3.10 example.py
3.10.15
查看Python版本请求文档
关于请求 Python 版本更详细的信息。
使用GUI脚本
在 Windows 上,uv
将使用 pythonw
运行扩展名为 .pyw
的脚本。
example.pyw
from tkinter import Tk, ttkroot = Tk()
root.title("uv")
frm = ttk.Frame(root, padding=10)
frm.grid()
ttk.Label(frm, text="Hello World").grid(column=0, row=0)
root.mainloop()
PS> uv run example.pyw
同样,它与依赖项一起工作:
example_pyqt.pyw
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QGridLayoutapp = QApplication(sys.argv)
widget = QWidget()
grid = QGridLayout()text_label = QLabel()
text_label.setText("Hello World!")
grid.addWidget(text_label)widget.setLayout(grid)
widget.setGeometry(100, 100, 200, 50)
widget.setWindowTitle("uv")
widget.show()
sys.exit(app.exec_())
PS> uv run --with PyQt5 example_pyqt.pyw
下一步
要了解更多关于 uv run
的信息,请参阅命令参考。
或者,继续阅读了解如何使用uv 运行和安装工具。
2025年2月12日
构建和发布包
https://docs.astral.sh/uv/guides/package/
uv 支持通过 uv build
将 Python 包构建成源和二进制发行版,并通过 uv publish
将其上传到注册表。
为打包准备你的项目
在尝试发布你的项目之前,你想要确保它已经准备好可以打包分发。
如果你的项目在 pyproject.toml
中没有包含 [build-system]
定义,uv 将默认不构建它。这意味着你的项目可能还没有准备好分发。更多关于声明构建系统对项目概念的影响,请参阅 项目概念 文档。
注意 :
如果你有不想发布的内部包,你可以将它们标记为私有:
[project]
classifiers = ["Private :: Do Not Upload"]
此设置使 PyPI 拒绝您上传的软件包进行发布。它不会影响其他注册表上的安全或隐私设置。
我们也推荐只生成每个项目的令牌:如果没有与项目匹配的 PyPI 令牌,就无法意外发布。
构建您的包
使用 uv build
构建您的包:
uv build
默认情况下,uv build
将在当前目录中构建项目,并将构建的工件放置在 dist/
子目录中。
或者,uv build <SRC>
将在指定的目录中构建软件包,而 uv build --package <PACKAGE>
将在当前工作区中构建指定的软件包。
Info
默认情况下,uv build
会尊重 tool.uv.sources
当从 pyproject.toml
的 build-system.requires
部分解析构建依赖时。当发布一个包时,我们建议运行 uv build --no-sources
以确保在禁用 tool.uv.sources
时,包能够正确构建,就像在使用其他构建工具,如 pypa/build
时一样。pypa/build。
发布您的包
使用 uv publish
发布您的包:
uv publish
设置 PyPI 令牌使用 --token
或 UV_PUBLISH_TOKEN
,或者使用 --username
或 UV_PUBLISH_USERNAME
设置用户名,并使用 --password
或 UV_PUBLISH_PASSWORD
设置密码。从 GitHub Actions 发布到 PyPI 时,您不需要设置任何凭证。相反,将受信任的发布者添加到 PyPI 项目。
Note : PyPI 不再支持使用用户名和密码进行发布,而是需要生成一个令牌。使用令牌相当于设置 --username __token__
并使用令牌作为密码。
如果您正在使用通过 [[tool.uv.index]]
定制的索引,请添加 publish-url
并使用 uv publish --index <name>
。例如:
[[tool.uv.index]]
name = "testpypi"
url = "https://test.pypi.org/simple/"
publish-url = "https://test.pypi.org/legacy/"
explicit = true
Note : 当使用 uv publish --index <name>
时,必须存在 pyproject.toml
文件,即你需要在发布 CI 作业中包含一个检出步骤。
尽管 uv publish
会重试失败的上传,但可能会发生发布过程中断的情况,一些文件已上传,而一些文件仍然缺失。对于 PyPI,您可以重试完全相同的命令,现有的相同文件将被忽略。对于其他仓库,使用 --check-url <index url>
与包所属的索引 URL(不是发布 URL)。当使用 --index
时,索引 URL 被用作检查 URL。uv 将跳过与仓库中文件相同的文件上传,它还会处理并发的并行上传。请注意,现有文件需要与之前上传到仓库的文件完全匹配,这可以避免意外发布具有不同内容的同一版本的源分布和 wheel 文件。
安装您的包
测试该软件包是否可以使用 uv 运行
进行安装和导入:
uv run --with <PACKAGE> --no-project -- python -c "import <PACKAGE>"
--no-project
标志用于避免从您的本地项目目录中安装包。
Tip : 如果您最近安装了该软件包,您可能需要包含 --refresh-package <PACKAGE>
选项以避免使用软件包的缓存版本。
集成指南
了解如何将 uv 与其他软件集成:
- 在 Docker 镜像中使用
- 与 Jupyter 一起使用
- 与 pre-commit 一起使用
- 在 GitHub Actions 中使用
- 在 GitLab CI/CD 中使用
- 使用替代包索引
- 安装 PyTorch
- 构建 FastAPI 应用程序
- 与 AWS Lambda 一起使用
或者,探索 概念文档 以获取每个功能的全面说明。
2025年1月7日
在Docker中使用uv
https://docs.astral.sh/uv/guides/integration/docker/
入门
提示:查看uv-docker-example项目,了解使用uv在Docker中构建应用程序的最佳实践示例。
uv提供了两种distroless Docker镜像,这些镜像对于将uv二进制文件安装uv到您自己的镜像构建中非常有用,以及从流行的基础镜像派生的镜像,这些镜像对于在容器中使用uv非常有用。
distroless镜像除了uv二进制文件外不包含任何内容。相比之下,派生的镜像包括预安装了uv的操作系统。
例如,要使用基于Debian的镜像在容器中运行uv:
docker run --rm -it ghcr.io/astral-sh/uv:debian uv --help
可用镜像
以下distroless镜像可用:
ghcr.io/astral-sh/uv:latest
ghcr.io/astral-sh/uv:{major}.{minor}.{patch}
, 例如,ghcr.io/astral-sh/uv:0.6.3
ghcr.io/astral-sh/uv:{major}.{minor}
, 例如,ghcr.io/astral-sh/uv:0.6
(最新的补丁版本)
以下是一些派生镜像:
- 基于
alpine:3.20
:ghcr.io/astral-sh/uv:alpine
ghcr.io/astral-sh/uv:alpine3.20
- 基于
debian:bookworm-slim
:ghcr.io/astral-sh/uv:debian-slim
ghcr.io/astral-sh/uv:bookworm-slim
- 基于
buildpack-deps:bookworm
:ghcr.io/astral-sh/uv:debian
ghcr.io/astral-sh/uv:bookworm
- 基于
python3.x-alpine
:ghcr.io/astral-sh/uv:python3.13-alpine
ghcr.io/astral-sh/uv:python3.12-alpine
ghcr.io/astral-sh/uv:python3.11-alpine
ghcr.io/astral-sh/uv:python3.10-alpine
ghcr.io/astral-sh/uv:python3.9-alpine
ghcr.io/astral-sh/uv:python3.8-alpine
- 基于
python3.x-bookworm
:ghcr.io/astral-sh/uv:python3.13-bookworm
ghcr.io/astral-sh/uv:python3.12-bookworm
ghcr.io/astral-sh/uv:python3.11-bookworm
ghcr.io/astral-sh/uv:python3.10-bookworm
ghcr.io/astral-sh/uv:python3.9-bookworm
ghcr.io/astral-sh/uv:python3.8-bookworm
- 基于
python3.x-slim-bookworm
:ghcr.io/astral-sh/uv:python3.13-bookworm-slim
ghcr.io/astral-sh/uv:python3.12-bookworm-slim
ghcr.io/astral-sh/uv:python3.11-bookworm-slim
ghcr.io/astral-sh/uv:python3.10-bookworm-slim
ghcr.io/astral-sh/uv:python3.9-bookworm-slim
ghcr.io/astral-sh/uv:python3.8-bookworm-slim
与distroless镜像一样,每个派生镜像都使用uv版本标签以 ghcr.io/astral-sh/uv:{major}.{minor}.{patch}-{base}
和ghcr.io/astral-sh/uv:{major}.{minor}-{base}
的形式发布,例如,ghcr.io/astral-sh/uv:0.6.3-alpine
。
有关更多详细信息,请参阅GitHub容器页面。
安装uv
使用上述带预安装uv的镜像之一,或者通过从官方distroless Docker镜像复制二进制文件来安装uv:
Dockerfile
FROM python:3.12-slim-bookworm
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
或者,使用安装程序:
Dockerfile
FROM python:3.12-slim-bookworm# The installer requires curl (and certificates) to download the release archive
RUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates# Download the latest installer
ADD https://astral.sh/uv/install.sh /uv-installer.sh# Run the installer then remove it
RUN sh /uv-installer.sh && rm /uv-installer.sh# Ensure the installed binary is on the `PATH`
ENV PATH="/root/.local/bin/:$PATH"
注意,这需要 curl
可用。
在任何情况下,最佳实践是针对特定的uv版本进行固定,例如使用:
COPY --from=ghcr.io/astral-sh/uv:0.6.9 /uv /uvx /bin/
Tip : 虽然上面的Dockerfile示例指定了特定的标签,但也可以指定特定的SHA256。在需要可重复构建的环境中将特定SHA256视为最佳实践,因为标签可以在不同的提交SHA之间移动。
# e.g., using a hash from a previous release
COPY --from=ghcr.io/astral-sh/uv@sha256:2381d6aa60c326b71fd40023f921a0a3b8f91b14d5db6b90402e65a635053709 /uv /uvx /bin/
或者,使用安装程序:
ADD https://astral.sh/uv/0.6.9/install.sh /uv-installer.sh
安装项目
如果您使用 uv 来管理您的项目,您可以将它复制到镜像中并安装:
Dockerfile
# Copy the project into the image
ADD . /app# Sync the project into a new environment, using the frozen lockfile
WORKDIR /app
RUN uv sync --frozen
重要提醒 : 最佳实践是在您的仓库中添加 .venv
到 .dockerignore
文件 以防止它被包含在镜像构建中。项目虚拟环境依赖于您的本地平台,应在镜像中从头创建。
然后,要默认启动您的应用程序:
Dockerfile
# Presuming there is a `my_app` command provided by the project
CMD ["uv", "run", "my_app"]
Tip : 最佳实践是使用中间层来分隔依赖项的安装和项目本身,以提高 Docker 镜像构建时间。
查看 uv-docker-example
项目的完整示例uv-docker-example.
使用环境
一旦项目安装完成,您可以通过将二进制目录放置在路径的最前面来 激活 项目虚拟环境:
Dockerfile
ENV PATH="/app/.venv/bin:$PATH"
或者,您可以使用 uv run
来运行需要环境的任何命令:
Dockerfile
RUN uv run some_script.py
Tip : 或者,在同步之前可以设置UV_PROJECT_ENVIRONMENT
设置,以便将安装到系统 Python 环境中并完全跳过环境激活。
使用已安装的工具
要使用已安装的工具,请确保 工具 bin 目录 在路径上:
Dockerfile
ENV PATH=/root/.local/bin:$PATH
RUN uv tool install cowsay
docker run -it $(docker build -q .) /bin/bash -c "cowsay -t hello"
Note : 工具的 bin 目录位置可以通过在容器中运行 uv tool dir --bin
命令来确定。
或者,它也可以设置为固定位置:
Dockerfile
ENV UV_TOOL_BIN_DIR=/opt/uv-bin/
在musl-based镜像中安装Python
虽然uv 如果镜像中没有可用的Python版本,则会安装一个兼容的Python版本,但uv目前尚不支持为musl-based发行版安装Python。例如,如果您正在使用一个没有安装Python的Alpine Linux基础镜像,您需要使用系统包管理器添加它:
apk add --no-cache python3~=3.12
在容器中开发
当进行开发时,将项目目录挂载到容器中非常有用。在这种设置下,项目更改可以立即反映在容器化服务中,而无需重新构建镜像。然而,重要的是 不要 将项目虚拟环境(.venv
)包含在挂载中,因为虚拟环境是平台特定的,并且应该保留为镜像构建的版本。
使用 docker run
挂载项目
使用绑定挂载将项目(在工作目录中)绑定到 /app
,同时保留 .venv
目录并使用 匿名卷:
docker run --rm --volume .:/app --volume /app/.venv [...]
Tip : --rm
标志包含在内以确保容器和匿名卷在容器退出时被清理。
查看一个完整的示例,请参阅uv-docker-example
项目。
使用 docker compose
配置 watch
当使用Docker Compose时,容器开发可用的工具更为丰富。 watch
选项提供了比绑定挂载更精细的控制,并支持在文件更改时触发容器化服务的更新。
Note : 此功能需要Compose 2.22.0,该版本包含在Docker Desktop 4.24中。
在您的 Docker compose 文件 中配置 watch
,以便在不同步项目虚拟环境的情况下挂载项目目录,并在配置更改时重新构建镜像:
compose.yaml
services:example:build: .# ...develop:# Create a `watch` configuration to update the app#watch:# Sync the working directory with the `/app` directory in the container- action: syncpath: .target: /app# Exclude the project virtual environmentignore:- .venv/# Rebuild the image on changes to the `pyproject.toml`- action: rebuildpath: ./pyproject.toml
然后,运行 docker compose watch
以运行具有开发设置的容器。
查看一个完整的示例,请访问uv-docker-example
项目。
优化
编译字节码
将 Python 源文件编译为字节码通常对于生产镜像来说是可取的,因为它往往会提高启动时间(以增加安装时间为代价)。
要启用字节码编译,请使用 --compile-bytecode
标志:
Dockerfile
RUN uv sync --compile-bytecode
或者,您可以将 UV_COMPILE_BYTECODE
环境变量设置为确保 Dockerfile 中所有命令都编译字节码:
Dockerfile
ENV UV_COMPILE_BYTECODE=1
缓存
缓存挂载(cache mount)可以用来提高构建过程中的性能:
Dockerfile
ENV UV_LINK_MODE=copyRUN --mount=type=cache,target=/root/.cache/uv \uv sync
更改默认的UV_LINK_MODE
将静默关于无法使用硬链接的警告,因为缓存和同步目标位于不同的文件系统上。
如果您没有挂载缓存,可以通过使用 --no-cache
标志或设置 UV_NO_CACHE
来减少图像大小。
Note : 缓存目录的位置可以通过在容器中运行 uv cache dir
命令来确定。
或者,可以将缓存设置为一个固定位置:
Dockerfile
ENV UV_CACHE_DIR=/opt/uv-cache/
中级层
如果您使用 uv 来管理项目,您可以通过使用 --no-install
选项将传递依赖项安装移入其自己的层来提高构建时间。
uv sync --no-install-project
将安装项目的依赖项,但不会安装项目本身。由于项目经常更改,但其依赖项通常是静态的,这可以节省大量时间。
Dockerfile
# Install uv
FROM python:3.12-slim
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/# Change the working directory to the `app` directory
WORKDIR /app# Install dependencies
RUN --mount=type=cache,target=/root/.cache/uv \--mount=type=bind,source=uv.lock,target=uv.lock \--mount=type=bind,source=pyproject.toml,target=pyproject.toml \uv sync --frozen --no-install-project# Copy the project into the image
ADD . /app# Sync the project
RUN --mount=type=cache,target=/root/.cache/uv \uv sync --frozen
注意,pyproject.toml
是必需的,用于标识项目根目录和名称,但项目 内容 不会在最终的 uv sync
命令之前被复制到镜像中。
Tip : 如果您正在使用一个工作区,则使用--no-install-workspace
标志,该标志将排除项目以及任何工作区成员。
如果您想从同步中移除特定的包,请使用 --no-install-package <名称>
。
不可编辑的安装
默认情况下,uv 以可编辑模式安装项目和工作空间成员,因此对源代码的更改将立即反映在环境中。
uv sync
和 uv run
都接受一个 --no-editable
标志,该标志指示 uv 以非可编辑模式安装项目,去除对源代码的任何依赖。
在多阶段 Docker 镜像的上下文中,可以使用 --no-editable
将项目包含在从一阶段同步的虚拟环境中,然后将虚拟环境本身(而不是源代码)单独复制到最终镜像中。
例如:
Dockerfile
# Install uv
FROM python:3.12-slim AS builder
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/# Change the working directory to the `app` directory
WORKDIR /app# Install dependencies
RUN --mount=type=cache,target=/root/.cache/uv \--mount=type=bind,source=uv.lock,target=uv.lock \--mount=type=bind,source=pyproject.toml,target=pyproject.toml \uv sync --frozen --no-install-project --no-editable# Copy the project into the intermediate image
ADD . /app# Sync the project
RUN --mount=type=cache,target=/root/.cache/uv \uv sync --frozen --no-editableFROM python:3.12-slim# Copy the environment, but not the source code
COPY --from=builder --chown=app:app /app/.venv /app/.venv# Run the application
CMD ["/app/.venv/bin/hello"]
使用 uv 临时
如果最终图像中不需要 uv,二进制文件可以在每次调用中挂载:
Dockerfile
RUN --mount=from=ghcr.io/astral-sh/uv,source=/uv,target=/bin/uv \uv sync
使用pip接口
安装一个包
在这个上下文中,系统Python环境是安全的,因为容器已经隔离。可以使用--system
标志在系统环境中安装:
Dockerfile
RUN uv pip install --system ruff
要使用系统 Python 环境作为默认环境,设置 UV_SYSTEM_PYTHON
变量:
Dockerfile
ENV UV_SYSTEM_PYTHON=1
或者,可以创建并激活一个虚拟环境:
Dockerfile
RUN uv venv /opt/venv
# Use the virtual environment automatically
ENV VIRTUAL_ENV=/opt/venv
# Place entry points in the environment at the front of the path
ENV PATH="/opt/venv/bin:$PATH"
当使用虚拟环境时,应从 uv 调用中省略 --system
标志:
Dockerfile
RUN uv pip install ruff
安装依赖项
要安装依赖项文件,请将它们复制到容器中:
Dockerfile
COPY requirements.txt .
RUN uv pip install -r requirements.txt
安装项目
当在安装项目的同时安装需求时,最佳实践是将复制需求与源代码的其他部分分开。这允许项目的依赖项(这些依赖项不经常更改)与项目本身(更改非常频繁)分别缓存。
Dockerfile
COPY pyproject.toml .
RUN uv pip install -r pyproject.toml
COPY . .
RUN uv pip install -e .
验证图像来源
Docker 镜像在构建过程中进行签名,以提供其来源的证明。这些证明可以用来验证镜像是否由官方渠道生产。
例如,您可以使用 GitHub CLI 工具 gh
验证这些证明:
gh attestation verify --owner astral-sh oci://ghcr.io/astral-sh/uv:latest
这表明特定的Docker镜像是由官方uv Github发布工作流程构建的,并且自那以后没有被篡改。
GitHub 认证建立在 sigstore.dev 基础设施之上。因此,您也可以使用cosign
命令来验证认证 blob 与 uv
的(多平台)清单。
REPO=astral-sh/uv
gh attestation download --repo $REPO oci://ghcr.io/${REPO}:latestdocker buildx imagetools inspect ghcr.io/${REPO}:latest --format "{{json .Manifest}}" > manifest.json
cosign verify-blob-attestation \--new-bundle-format \--bundle "$(jq -r .digest manifest.json).jsonl" \--certificate-oidc-issuer="https://token.actions.githubusercontent.com" \--certificate-identity-regexp="^https://github.com/${REPO}/.*" \<(jq -j '.|del(.digest,.size)' manifest.json)
Tip : 这些示例使用 latest
,但最佳实践是验证特定版本标签的证明,例如 ghcr.io/astral-sh/uv:0.6.3
,或者(更好的是)特定的镜像摘要,例如 ghcr.io/astral-sh/uv:0.5.27@sha256:5adf09a5a526f380237408032a9308000d14d5947eafa687ad6c6a2476787b4f
。
2025年2月24日
使用uv与Jupyter
Jupyter笔记本是一个流行的交互式计算、数据分析可视化的工具。您可以使用Jupyter与uv以几种不同的方式,无论是与项目交互,还是作为一个独立的工具。
在项目中使用Jupyter
如果您在一个项目中工作,您可以通过以下方式启动一个Jupyter服务器,并访问项目的虚拟环境:
uv run --with jupyter jupyter lab
默认情况下,jupyter lab
将在 http://localhost:8888/lab 启动服务器。
在笔记本中,您可以像在项目中的任何其他文件中一样导入您的项目模块。例如,如果您的项目依赖于 requests
,则 import requests
将从项目的虚拟环境中导入 requests
。
如果您正在寻找对项目虚拟环境的只读访问权限,那么就没有更多的事情需要做。然而,如果您需要在笔记本内安装额外的包,那么有一些额外的细节需要考虑。
创建内核
如果您需要在笔记本中安装包,我们建议为您的项目创建一个专用的内核。内核使 Jupyter 服务器能够在单一环境中运行,而各个笔记本则在自己的独立环境中运行。
在 uv 的上下文中,我们可以在安装 Jupyter 本身的同时,在隔离环境中为项目创建一个内核,例如 uv run --with jupyter jupyter lab
。为项目创建内核确保了笔记本连接到正确的环境,并且任何从笔记本内部安装的包都会安装到项目的虚拟环境中。
要创建一个内核,您需要将 ipykernel
作为开发依赖项安装:
uv add --dev ipykernel
然后,您可以使用以下命令为 project
创建内核:
uv run ipython kernel install --user --env VIRTUAL_ENV $(pwd)/.venv --name=project
从那里开始,使用以下命令启动服务器:
uv run --with jupyter jupyter lab
创建笔记本时,从下拉菜单中选择 项目
内核。然后使用 !uv add pydantic
将 pydantic
添加到项目的依赖项中,或者使用 !uv pip install pydantic
将 pydantic
安装到项目的虚拟环境中,而不会将更改持久化到项目的 pyproject.toml
或 uv.lock
文件中。任一命令都将使 import pydantic
在笔记本中工作。
在没有内核的情况下安装软件包
如果您不想创建内核,您仍然可以在笔记本内部安装包。但是,有一些注意事项需要考虑。
尽管 uv run --with jupyter
在一个隔离的环境中运行,但在笔记本本身中,!uv add
和相关命令将修改 项目 的环境,即使没有内核。
例如,在笔记本中运行 !uv add pydantic
将会将 pydantic
添加到项目的依赖项和虚拟环境中,这样 import pydantic
将会立即工作,无需进一步配置或重启服务器。
然而,由于 Jupyter 服务器是“活动”环境,!uv pip install
将会将包安装到 Jupyter 的环境中,而不是项目环境。这些依赖将存在于 Jupyter 服务器的整个生命周期中,但在随后的 jupyter
调用中可能会消失。
如果您正在使用依赖于pip(例如,通过 %pip
魔法命令)的笔记本,您可以通过在启动Jupyter服务器之前运行 uv venv --seed
命令来将pip包含在您的项目虚拟环境中。例如,给定:
uv venv --seed
uv run --with jupyter jupyter lab
后续在笔记本中执行的 %pip install
调用将包安装到项目的虚拟环境中。然而,此类修改 不会 反映在项目的 pyproject.toml
或 uv.lock
文件中。
使用 Jupyter 作为独立工具
如果您需要临时访问一个笔记本(即,交互式运行Python代码片段),您可以通过运行uv tool run jupyter lab
在任何时候启动一个Jupyter服务器。这将在一个隔离的环境中运行一个Jupyter服务器。
使用 Jupyter 非项目环境
如果您需要在未与项目相关联的虚拟环境中运行 Jupyter(例如,没有 pyproject.toml
或 uv.lock
),您可以直接将 Jupyter 添加到环境中。例如:
macOS 和 Linux
uv venv --seed
uv pip install pydantic
uv pip install jupyterlab
.venv/bin/jupyter lab
Windows
uv venv --seed
uv pip install pydantic
uv pip install jupyterlab
.venv\Scripts\jupyter lab
从这里,import pydantic
将在笔记本中工作,您可以通过 !uv pip install
安装额外的包,甚至 !pip install
。
使用 VS Code 中的 Jupyter
您也可以在 VS Code 等编辑器内与 Jupyter notebooks 进行交互。要将 uv-managed 项目连接到 VS Code 内的 Jupyter notebook,我们建议为项目创建一个内核,如下所示:
# Create a project.
uv init project# Move into the project directory.
cd project# Add ipykernel as a dev dependency.
uv add --dev ipykernel# Open the project in VS Code.
code .
一旦在 VS Code 中打开了项目目录,您可以通过从命令面板中选择“创建:新建 Jupyter Notebook”来创建一个新的 Jupyter Notebook。当提示选择内核时,选择“Python 环境”并选择您之前创建的虚拟环境(例如,在 macOS 和 Linux 上为 .venv/bin/python
,在 Windows 上为 .venv\Scripts\python
)。
Note : VS Code 需要在项目环境中存在 ipykernel
。如果您希望避免将 ipykernel
添加为开发依赖项,可以直接使用 uv pip install ipykernel
将其安装到项目环境中。
如果您需要在笔记本内操作项目的环境,您可能需要将 uv
添加为显式的开发依赖项:
uv add --dev uv
从那里,您可以使用 !uv add pydantic
将 pydantic
添加到项目的依赖项中,或者使用 !uv pip install pydantic
将 pydantic
安装到项目的虚拟环境中,而无需更新项目的 pyproject.toml
或 uv.lock
文件。
2025年2月1日
在 GitHub Actions 中使用 uv
安装
对于与 GitHub Actions 一起使用,我们推荐官方的
astral-sh/setup-uv
操作,该操作安装 uv,将其添加到 PATH,(可选)持久化缓存,等等,支持所有 uv 支持的平台。
要安装 uv 的最新版本:
example.yml
name: Examplejobs:uv-example:name: pythonruns-on: ubuntu-lateststeps:- uses: actions/checkout@v4- name: Install uvuses: astral-sh/setup-uv@v5
被认为是最佳实践将固定到特定的uv版本,例如:
example.yml
name: Examplejobs:uv-example:name: pythonruns-on: ubuntu-lateststeps:- uses: actions/checkout@v4- name: Install uvuses: astral-sh/setup-uv@v5with:# Install a specific version of uv.version: "0.6.9"
设置 Python
Python 可以使用 python install
命令进行安装:
example.yml
name: Examplejobs:uv-example:name: pythonruns-on: ubuntu-lateststeps:- uses: actions/checkout@v4- name: Install uvuses: astral-sh/setup-uv@v5- name: Set up Pythonrun: uv python install
这将尊重项目中指定的 Python 版本。
或者,可以使用官方的 GitHub setup-python
动作。这可能会更快,因为 GitHub 将 Python 版本与运行器一起缓存。
设置 python-version-file
选项 让项目使用固定版本:
example.yml
name: Examplejobs:uv-example:name: pythonruns-on: ubuntu-lateststeps:- uses: actions/checkout@v4- name: Install uvuses: astral-sh/setup-uv@v5- name: "Set up Python"uses: actions/setup-python@v5with:python-version-file: ".python-version"
或者,指定 pyproject.toml
文件以忽略pin,并使用与项目的 requires python
约束兼容的最新版本:
example.yml
name: Examplejobs:uv-example:name: pythonruns-on: ubuntu-lateststeps:- uses: actions/checkout@v4- name: Install uvuses: astral-sh/setup-uv@v5- name: "Set up Python"uses: actions/setup-python@v5with:python-version-file: "pyproject.toml"
多个 Python 版本
当使用矩阵测试多个 Python 版本时,使用 astral-sh/setup-uv
设置 Python 版本,这将覆盖 pyproject.toml
或 .python-version
文件中的 Python 版本指定:
example.yml
jobs:build:name: continuous-integrationruns-on: ubuntu-lateststrategy:matrix:python-version:- "3.10"- "3.11"- "3.12"steps:- uses: actions/checkout@v4- name: Install uv and set the python versionuses: astral-sh/setup-uv@v5with:python-version: ${{ matrix.python-version }}
如果不使用 setup-uv
动作,您可以设置 UV_PYTHON
环境变量:
example.yml
jobs:build:name: continuous-integrationruns-on: ubuntu-lateststrategy:matrix:python-version:- "3.10"- "3.11"- "3.12"env:UV_PYTHON: ${{ matrix.python-version }}steps:- uses: actions/checkout@v4
同步和运行
一旦安装了 uv 和 Python,可以使用 uv sync
安装项目,并使用 uv run
在环境中运行命令:
example.yml
name: Examplejobs:uv-example:name: pythonruns-on: ubuntu-lateststeps:- uses: actions/checkout@v4- name: Install uvuses: astral-sh/setup-uv@v5- name: Install the projectrun: uv sync --all-extras --dev- name: Run tests# For example, using `pytest`run: uv run pytest tests
Tip: UV_PROJECT_ENVIRONMENT
setting 可用于安装到系统Python环境,而不是创建虚拟环境。
缓存
存储 uv 的缓存跨工作流程运行可能会提高 CI 的时间。
astral-sh/setup-uv
有内置支持持久化缓存:
example.yml
- name: Enable cachinguses: astral-sh/setup-uv@v5with:enable-cache: true
您可以在运行器上配置操作以使用自定义缓存目录:
example.yml
- name: Define a custom uv cache pathuses: astral-sh/setup-uv@v5with:enable-cache: truecache-local-path: "/path/to/cache"
或者当 lockfile 更改时使其无效:
example.yml
- name: Define a cache dependency globuses: astral-sh/setup-uv@v5with:enable-cache: truecache-dependency-glob: "uv.lock"
或者当任何需求文件更改时:
example.yml
- name: Define a cache dependency globuses: astral-sh/setup-uv@v5with:enable-cache: truecache-dependency-glob: "requirements**.txt"
请注意,astral-sh/setup-uv
将会为每个主机自动使用一个单独的缓存密钥
架构和平台。
或者,您可以使用 actions/cache
动作手动管理缓存:
example.yml
jobs:install_job:env:# Configure a constant location for the uv cacheUV_CACHE_DIR: /tmp/.uv-cachesteps:# ... setup up Python and uv ...- name: Restore uv cacheuses: actions/cache@v4with:path: /tmp/.uv-cachekey: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}restore-keys: |uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}uv-${{ runner.os }}# ... install packages, run tests, etc ...- name: Minimize uv cacherun: uv cache prune --ci
uv cache prune --ci
命令用于减小缓存大小,并针对 CI 进行了优化。
其性能影响取决于已安装的软件包。
提示:如果使用 uv pip
,请使用 requirements.txt
而不是 uv.lock
作为缓存键。
当使用非临时的、自托管的运行程序时,默认缓存目录可以无限增长。在这种情况下,在作业之间共享缓存可能不是最佳选择。相反,在GitHub工作区内移动缓存,并在作业完成后使用 Post Job Hook 将其移除。
install_job:env:# Configure a relative location for the uv cacheUV_CACHE_DIR: ${{ github.workspace }}/.cache/uv
使用后期作业挂钩需要将自宿主运行程序上的 ACTIONS_RUNNER_HOOK_JOB_STARTED
环境变量设置为清理脚本的路径,如下图所示。
clean-uv-cache.sh
#!/usr/bin/env sh
uv cache clean
使用 uv pip
如果使用 uv pip
接口而不是 uv 项目接口,uv 默认需要虚拟环境。要允许将包安装到系统环境,请在所有 uv
调用中使用 --system
标志或设置 UV_SYSTEM_PYTHON
变量。
UV_SYSTEM_PYTHON
变量可以在不同的作用域中定义。
通过在顶层定义它来选择整个工作流程:
example.yml
env:UV_SYSTEM_PYTHON: 1jobs: ...
或者,选择工作流程中的特定工作:
example.yml
jobs:install_job:env:UV_SYSTEM_PYTHON: 1...
或者,选择特定工作步骤的订阅:
example.yml
steps:- name: Install requirementsrun: uv pip install -r requirements.txtenv:UV_SYSTEM_PYTHON: 1
要再次退出,可以在任何uv调用中使用 --no-system
标志。
2025年2月24日
使用 uv 在 GitLab CI/CD 中
使用 uv 镜像
Astral 提供了预装 uv 的 Docker 镜像。选择一个适合您工作流程的变体。
gitlab-ci.yml
variables:UV_VERSION: 0.5PYTHON_VERSION: 3.12BASE_LAYER: bookworm-slim# GitLab CI creates a separate mountpoint for the build directory,# so we need to copy instead of using hard links.UV_LINK_MODE: copyuv:image: ghcr.io/astral-sh/uv:$UV_VERSION-python$PYTHON_VERSION-$BASE_LAYERscript:# your `uv` commands
Note : 如果您正在使用distroless镜像,您必须指定入口点:
uv:image:name: ghcr.io/astral-sh/uv:$UV_VERSIONentrypoint: [""]# ...
缓存
在流程运行之间持久化 uv 缓存可以提高性能。
uv-install:variables:UV_CACHE_DIR: .uv-cachecache:- key:files:- uv.lockpaths:- $UV_CACHE_DIRscript:# Your `uv` commands- uv cache prune --ci
查看 GitLab 缓存文档 以获取更多关于配置缓存的详细信息。
使用 uv cache prune --ci
在作业结束时推荐以减少缓存大小。有关更多详细信息,请参阅 uv cache 文档。
使用 uv pip
如果使用 uv pip
接口而不是 uv 项目的接口,uv 默认要求使用虚拟环境。要允许将包安装到系统环境,请在所有 uv 调用中使用 --system
标志或设置 UV_SYSTEM_PYTHON
变量。
UV_SYSTEM_PYTHON
变量可以在不同的作用域中定义。您可以在 GitLab 的文档中了解更多关于 变量及其优先级的工作方式。
选择整个工作流程,通过在顶层定义它进行注册:
gitlab-ci.yml
variables:UV_SYSTEM_PYTHON: 1# [...]
要再次取消订阅,可以在任何 uv 调用中使用 --no-system
标志。
在持久化缓存时,您可能希望使用 requirements.txt
或 pyproject.toml
作为您的缓存键文件,而不是 uv.lock
。
2025年1月29日
在 pre-commit 使用 uv
https://docs.astral.sh/uv/guides/integration/pre-commit/
官方的 pre-commit 钩子由 astral-sh/uv-pre-commit
提供。https://github.com/astral-sh/uv-pre-commit.
为确保即使 pyproject.toml
文件通过 pre-commit 被更改,您的 uv.lock
文件也保持最新,请将以下内容添加到 .pre-commit-config.yaml
文件中:
.pre-commit-config.yaml
repos:- repo: https://github.com/astral-sh/uv-pre-commit# uv version.rev: 0.6.9hooks:- id: uv-lock
为了使用 pre-commit 保持您的 requirements.txt
文件更新:
.pre-commit-config.yaml
repos:- repo: https://github.com/astral-sh/uv-pre-commit# uv version.rev: 0.6.9hooks:- id: uv-export
要将要求通过 pre-commit 编译,请将以下内容添加到 .pre-commit-config.yaml
文件中:
.pre-commit-config.yaml
repos:- repo: https://github.com/astral-sh/uv-pre-commit# uv version.rev: 0.6.9hooks:# Compile requirements- id: pip-compileargs: [requirements.in, -o, requirements.txt]
要编译替代文件,修改 args
和 files
:
.pre-commit-config.yaml
repos:- repo: https://github.com/astral-sh/uv-pre-commit# uv version.rev: 0.6.9hooks:# Compile requirements- id: pip-compileargs: [requirements-dev.in, -o, requirements-dev.txt]files: ^requirements-dev.(in|txt)$
要同时运行钩子覆盖多个文件:
.pre-commit-config.yaml
repos:- repo: https://github.com/astral-sh/uv-pre-commit# uv version.rev: 0.6.9hooks:# Compile requirements- id: pip-compilename: pip-compile requirements.inargs: [requirements.in, -o, requirements.txt]- id: pip-compilename: pip-compile requirements-dev.inargs: [requirements-dev.in, -o, requirements-dev.txt]files: ^requirements-dev.(in|txt)$
2025年2月24日
使用 uv 与 PyTorch
https://docs.astral.sh/uv/guides/integration/pytorch/
PyTorch生态系统是深度学习研究和开发的一个流行选择。您可以使用uv来管理PyTorch项目以及跨不同Python版本和环境中的PyTorch依赖项,甚至控制加速器的选择(例如,仅CPU与CUDA)。
注意 :
本指南中概述的一些功能需要uv版本0.5.3或更高版本。如果您正在使用uv的旧版本,我们建议在配置PyTorch之前进行升级。
安装 PyTorch
从打包的角度来看,PyTorch有一些不常见的特性:
- 许多PyTorch wheel托管在专门的索引中,而不是Python包索引(PyPI)。因此,安装PyTorch通常需要配置项目以使用PyTorch索引。
- PyTorch为每个加速器(例如,仅CPU、CUDA)生成不同的构建。由于在发布或安装时没有标准化的机制来指定这些加速器,PyTorch将它们编码在本地版本指定器中。因此,PyTorch版本通常会看起来像
2.5.1+cpu
、2.5.1+cu121
等。 - 不同加速器的构建发布到不同的索引中。例如,
+cpu
构建发布在https://download.pytorch.org/whl/cpu,而+cu121
构建发布在https://download.pytorch.org/whl/cu121。
因此,必要的打包配置将根据您需要支持的平台和您想要启用的加速器而有所不同。
首先,考虑以下(默认)配置,该配置可以通过运行uv init --python 3.12
然后运行uv add torch torchvision
生成。
在这种情况下,PyTorch将从PyPI安装,该索引托管Windows和macOS的仅CPU wheel以及Linux上的GPU加速wheel(针对CUDA 12.4):
[project]
name = "project"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["torch>=2.6.0","torchvision>=0.21.0",
]
支持的 Python 版本
在撰写本文时,PyTorch 尚未发布适用于 Python 3.13 的 wheels;因此,具有 requires-python = ">=3.13"
的项目可能无法解析。请参阅兼容性矩阵。
这是一个适用于希望使用Windows和macOS上的CPU构建以及Linux上的CUDA启用构建的项目有效配置。然而,如果您需要支持不同的平台或加速器,您需要相应地配置项目。
使用 PyTorch 索引
在某些情况下,您可能希望在整个平台上使用特定的 PyTorch 变体。例如,您可能希望也在 Linux 上使用仅 CPU 的构建。
在这种情况下,第一步是将相关的 PyTorch 索引添加到您的 pyproject.toml
:
CPU-only
[[tool.uv.index]]
name = "pytorch-cpu"
url = "https://download.pytorch.org/whl/cpu"
explicit = true
CUDA 12.4
[[tool.uv.index]]
name = "pytorch-cu124"
url = "https://download.pytorch.org/whl/cu124"
explicit = true
我们推荐使用 explicit = true
以确保索引仅用于 torch
、torchvision
和其他 PyTorch 相关包,而不是像 jinja2
这样的通用依赖项,这些依赖项应继续从默认索引(PyPI)获取。
接下来,更新 pyproject.toml
文件,以便将 torch
和 torchvision
指向所需的索引:
CPU-only
[tool.uv.sources]
torch = [{ index = "pytorch-cpu" },
]
torchvision = [{ index = "pytorch-cpu" },
]
CUDA 12.4
PyTorch 没有为 macOS 发布 CUDA 版本。因此,我们通过 sys_platform
来控制 uv 使用 Linux 和 Windows 上的 PyTorch 索引,但在 macOS 上回退到 PyPI:
[tool.uv.sources]
torch = [{ index = "pytorch-cu124", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
]
torchvision = [{ index = "pytorch-cu124", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
]
作为一个完整的示例,以下项目将在所有平台上使用 PyTorch 的仅 CPU 构建:
[project]
name = "project"
version = "0.1.0"
requires-python = ">=3.12.0"
dependencies = ["torch>=2.6.0","torchvision>=0.21.0",
][tool.uv.sources]
torch = [{ index = "pytorch-cpu" },
]
torchvision = [{ index = "pytorch-cpu" },
][[tool.uv.index]]
name = "pytorch-cpu"
url = "https://download.pytorch.org/whl/cpu"
explicit = true
使用环境标记配置加速器
在某些情况下,您可能希望在一个环境中使用仅CPU的构建(例如,macOS和Windows),而在另一个环境中使用启用CUDA的构建(例如,Linux)。
使用 tool.uv.sources
,您可以使用环境标记来指定每个平台所需的索引。例如,以下配置将在Windows上使用PyTorch的仅CPU构建(以及macOS,通过回退到PyPI),并在Linux上使用启用CUDA的构建:
[project]
name = "project"
version = "0.1.0"
requires-python = ">=3.12.0"
dependencies = ["torch>=2.6.0","torchvision>=0.21.0",
][tool.uv.sources]
torch = [{ index = "pytorch-cpu", marker = "sys_platform != 'linux'" },{ index = "pytorch-cu124", marker = "sys_platform == 'linux'" },
]
torchvision = [{ index = "pytorch-cpu", marker = "sys_platform != 'linux'" },{ index = "pytorch-cu124", marker = "sys_platform == 'linux'" },
][[tool.uv.index]]
name = "pytorch-cpu"
url = "https://download.pytorch.org/whl/cpu"
explicit = true[[tool.uv.index]]
name = "pytorch-cu124"
url = "https://download.pytorch.org/whl/cu124"
explicit = true
同样,以下配置将使用 PyTorch 的 Windows 和 Linux 的 Intel GPU 构建,以及 macOS 上的仅 CPU 构建(通过回退到 PyPI):
[project]
name = "project"
version = "0.1.0"
requires-python = ">=3.12.0"
dependencies = ["torch>=2.6.0","torchvision>=0.21.0","pytorch-triton-xpu>=3.2.0 ; sys_platform == 'linux'",
][tool.uv.sources]
torch = [{ index = "pytorch-xpu", marker = "sys_platform == 'win32' or sys_platform == 'linux'" },
]
torchvision = [{ index = "pytorch-xpu", marker = "sys_platform == 'win32' or sys_platform == 'linux'" },
]
pytorch-triton-xpu = [{ index = "pytorch-xpu", marker = "sys_platform == 'linux'" },
][[tool.uv.index]]
name = "pytorch-xpu"
url = "https://download.pytorch.org/whl/xpu"
explicit = true
使用可选依赖配置加速器
在某些情况下,您可能希望在某些情况下使用仅CPU构建,在其他情况下使用CUDA启用构建,并通过用户提供的额外参数来切换选择(例如,uv sync --extra cpu
与 uv sync --extra cu124
)。
使用 tool.uv.sources
,您可以使用额外的标记来指定每个启用的额外参数的所需索引。例如,以下配置将使用PyTorch的仅CPU构建为 uv sync --extra cpu
,并为 uv sync --extra cu124
使用CUDA启用构建:
[project]
name = "project"
version = "0.1.0"
requires-python = ">=3.12.0"
dependencies = [][project.optional-dependencies]
cpu = ["torch>=2.6.0","torchvision>=0.21.0",
]
cu124 = ["torch>=2.6.0","torchvision>=0.21.0",
][tool.uv]
conflicts = [[{ extra = "cpu" },{ extra = "cu124" },],
][tool.uv.sources]
torch = [{ index = "pytorch-cpu", extra = "cpu" },{ index = "pytorch-cu124", extra = "cu124" },
]
torchvision = [{ index = "pytorch-cpu", extra = "cpu" },{ index = "pytorch-cu124", extra = "cu124" },
][[tool.uv.index]]
name = "pytorch-cpu"
url = "https://download.pytorch.org/whl/cpu"
explicit = true[[tool.uv.index]]
name = "pytorch-cu124"
url = "https://download.pytorch.org/whl/cu124"
explicit = true
Note : 由于 macOS 上不可用 GPU 加速构建,当启用 cu124
额外功能时,上述配置将在 macOS 上安装失败。
The uv pip
interface
虽然上述示例集中于uv的项目接口(uv lock
、uv sync
、uv run
等),PyTorch也可以通过uv pip
接口进行安装。
PyTorch 本身提供了一个 专用接口 来确定针对特定目标配置应运行的相应 pip 命令。例如,您可以在 Linux 上使用以下命令安装稳定版、仅 CPU 的 PyTorch:
$ pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
要使用与 uv 相同的工作流程,将 pip3
替换为 uv pip
:
uv pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
自动后端选择
在 预览 中,uv 可以通过 --torch-backend=auto
(或 UV_TORCH_BACKEND=auto
)通过检查系统配置在运行时自动选择适当的 PyTorch 索引:
uv_TORCH_BACKEND=auto uv pip install torch
当启用时,uv 将查询已安装的 CUDA 驱动程序版本,并使用所有相关软件包(例如,torch
、torchvision
等)最兼容的 PyTorch 索引。如果找不到这样的 CUDA 驱动程序,uv 将回退到仅 CPU 的索引。uv 将继续尊重 PyTorch 生态系统之外的任何软件包的现有索引配置。
要选择特定的后端(例如,cu126
),设置 --torch-backend=cu126
(或 UV_TORCH_BACKEND=cu126
)。
目前,--torch-backend
仅在 uv pip
接口可用,并且仅支持检测 CUDA 驱动程序(与其他加速器如 ROCm 或英特尔 GPU 相反)。
由于 --torch-backend
是一个预览功能,它应被视为实验性的,并且不受 uv 的标准 版本政策 约束。--torch-backend
可能会在 uv 的未来版本中更改或完全删除。
2025年1月30日
使用 uv 与 FastAPI
https://docs.astral.sh/uv/guides/integration/fastapi/
FastAPI 是一个现代、高性能的 Python 网络框架。您可以使用 uv 来管理您的 FastAPI 项目,包括安装依赖项、管理环境、运行 FastAPI 应用程序等。
注意:您可以在 uv-fastapi-example 仓库中查看本指南的源代码。
迁移现有的 FastAPI 项目
作为一个例子,考虑以下在 FastAPI 文档 中定义的示例应用程序,其结构如下:
project
└── app├── __init__.py├── main.py├── dependencies.py├── routers│ ├── __init__.py│ ├── items.py│ └── users.py└── internal├── __init__.py└── admin.py
要使用 uv 与此应用程序一起使用,请在 project
目录下运行:
uv init --app
这创建了一个具有应用程序布局的项目和一个 pyproject.toml
文件。
然后,添加对FastAPI的依赖:
uv add fastapi --extra standard
您现在应该具有以下结构:
project
├── pyproject.toml
└── app├── __init__.py├── main.py├── dependencies.py├── routers│ ├── __init__.py│ ├── items.py│ └── users.py└── internal├── __init__.py└── admin.py
并且 pyproject.toml
文件的内容应该看起来像这样:
pyproject.toml
[project]
name = "uv-fastapi-example"
version = "0.1.0"
description = "FastAPI project"
readme = "README.md"
requires-python = ">=3.12"
dependencies = ["fastapi[standard]",
]
从那里,您可以使用以下命令运行 FastAPI 应用程序:
uv run fastapi dev
uv run
将自动解析和锁定项目依赖(即在 pyproject.toml
旁边创建一个 uv.lock
),创建一个虚拟环境,并在该环境中运行命令。
通过在网页浏览器中打开 http://127.0.0.1:8000/?token=jessica 来测试应用。
部署
要部署 FastAPI 应用程序使用 Docker,你可以使用以下 Dockerfile
:
Dockerfile
FROM python:3.12-slim# Install uv.
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/# Copy the application into the container.
COPY . /app# Install the application dependencies.
WORKDIR /app
RUN uv sync --frozen --no-cache# Run the application.
CMD ["/app/.venv/bin/fastapi", "run", "app/main.py", "--port", "80", "--host", "0.0.0.0"]
使用以下命令构建 Docker 镜像:
docker build -t fastapi-app .
运行 Docker 容器本地使用:
docker run -p 8000:80 fastapi-app
导航到 http://127.0.0.1:8000/?token=jessica 在您的浏览器中,以验证应用是否正确运行。
Tip : 关于使用uv与Docker的更多信息,请参阅Docker指南。
2025年1月9日
使用替代包索引
虽然 uv 默认使用官方的 Python 包索引 (PyPI),但它也支持 替代包索引。大多数替代索引需要各种形式的身份验证,这需要一些初始设置。
Important:
如果您使用pip接口,请阅读uv上的使用多个索引文档——默认行为与pip不同,以防止依赖混淆攻击,但这意味着uv可能无法找到您预期的包版本。
Azure Artifacts
uv 可以从 Azure Artifacts 安装包,无论是通过使用 个人访问令牌 (PAT) 还是使用 keyring
包。
要使用 Azure Artifacts,将索引添加到您的项目:
pyproject.toml
[[tool.uv.index]]
name = "private-registry"
url = "https://pkgs.dev.azure.com/<ORGANIZATION>/<PROJECT>/_packaging/<FEED>/pypi/simple/"
使用 Azure 访问令牌进行身份验证
如果可用个人访问令牌(PAT)(例如,在 Azure 管道中的 $(System.AccessToken)
([https://learn.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml#systemaccesstoken))),则可以通过“基本”HTTP 身份验证方案提供凭据。请在 URL 的密码字段中包含 PAT。还必须包含一个用户名,但它可以是任何字符串。
例如,如果令牌存储在 $AZURE_ARTIFACTS_TOKEN
环境变量中,则可以使用以下命令为索引设置凭据:
export UV_INDEX_PRIVATE_REGISTRY_USERNAME=dummy
export UV_INDEX_PRIVATE_REGISTRY_PASSWORD="$AZURE_ARTIFACTS_TOKEN"
注意:PRIVATE_REGISTRY
应该与在您的 pyproject.toml
中定义的索引名称匹配。
使用 keyring
和 artifacts-keyring
进行认证
您还可以使用 keyring
包并通过 artifacts-keyring
插件 认证 Artifacts。由于这两个包是用于认证 Azure Artifacts 所必需的,因此它们必须从 Artifacts 以外的来源预先安装。
artifacts-keyring
插件封装了 Azure Artifacts 凭据提供程序工具。凭据提供程序支持几种不同的认证模式,包括交互式登录——有关配置信息,请参阅 工具的文档。
uv 仅支持在 子进程模式 下使用 keyring
包。keyring
可执行文件必须在 PATH
中,即全局安装或在活动环境中安装。keyring
CLI 需要在 URL 中包含用户名,并且必须是 VssSessionToken
。
# Pre-install keyring and the Artifacts plugin from the public PyPI
uv tool install keyring --with artifacts-keyring# Enable keyring authentication
export UV_KEYRING_PROVIDER=subprocess# Set the username for the index
export UV_INDEX_PRIVATE_REGISTRY_USERNAME=VssSessionToken
注意:可以使用tool.uv.keyring-provider设置来在您的uv.toml
或pyproject.toml
中启用密钥圈。
同样,索引的用户名可以直接添加到索引 URL 中。
将包发布到 Azure Artifacts
如果您也想将您自己的包发布到 Azure Artifacts,您可以使用 uv publish
,具体操作请参阅构建和发布指南。
首先,将一个 publish-url
添加到您想要发布包的索引中。例如:
pyproject.toml
[[tool.uv.index]]
name = "private-registry"
url = "https://pkgs.dev.azure.com/<ORGANIZATION>/<PROJECT>/_packaging/<FEED>/pypi/simple/"
publish-url = "https://pkgs.dev.azure.com/<ORGANIZATION>/<PROJECT>/_packaging/<FEED>/pypi/upload/"
然后,配置凭据(如果未使用 keyring):
$ export UV_PUBLISH_USERNAME=dummy
$ export UV_PUBLISH_PASSWORD="$AZURE_ARTIFACTS_TOKEN"
并且发布该包:
uv publish --index private-registry
要使用 uv publish
而不将 publish-url
添加到项目中,您可以设置 UV_PUBLISH_URL
:
$ export UV_PUBLISH_URL=https://pkgs.dev.azure.com/<ORGANIZATION>/<PROJECT>/_packaging/<FEED>/pypi/upload/
$ uv publ.sh
注意,此方法不推荐,因为uv无法在上传工件之前检查该包是否已发布。
GoogleArtifactRegistry
uv 可以从 GoogleArtifactRegistry 安装包,无论是通过使用访问令牌,还是使用 keyring
包。
注意:本指南假设已安装并认证了gcloud
CLI。
要使用 Google Artifact Registry,将索引添加到您的项目中:
pyproject.toml
[[tool.uv.index]]
name = "private-registry"
url = "https://<REGION>-python.pkg.dev/<PROJECT>/<REPOSITORY>"
使用 Google 访问令牌进行身份验证
凭据可以通过 “Basic” HTTP 认证方案提供。将访问令牌包含在 URL 的密码字段中。用户名必须是 oauth2accesstoken
,否则身份验证将失败。
使用 gcloud
生成令牌:
export ARTIFACT_REGISTRY_TOKEN=$(gcloud auth application-default print-access-token
)
注意:您可能需要传递额外的参数以正确生成令牌(如 --project
),这是一个基本示例。
然后使用以下命令为索引设置凭据:
export UV_INDEX_PRIVATE_REGISTRY_USERNAME=oauth2accesstoken
export UV_INDEX_PRIVATE_REGISTRY_PASSWORD="$ARTIFACT_REGISTRY_TOKEN"
注意:PRIVATE_REGISTRY
应与在您的 pyproject.toml
中定义的索引名称匹配。
使用 keyring
和 keyrings.google-artifactregistry-auth
进行认证
您还可以使用 keyring
包以及 keyrings.google-artifactregistry-auth
插件(GitHub 上的链接)对 Artifact Registry 进行认证。由于这两个包是认证到 Artifact Registry 所必需的,因此必须从除 Artifact Registry 以外的来源预先安装。
keyrings.google-artifactregistry-auth
插件包装了 gcloud CLI 以生成短期访问令牌,安全地将它们存储在系统密钥环中,并在它们过期时刷新它们。
uv 只支持在 子进程模式 中使用 keyring
包。keyring
可执行文件必须在 PATH
中,即全局安装或在活动环境中安装。keyring
CLI 需要在 URL 中指定用户名,并且它必须是 oauth2accesstoken
。
# Pre-install keyring and Artifact Registry plugin from the public PyPI
uv tool install keyring --with keyrings.google-artifactregistry-auth# Enable keyring authentication
export UV_KEYRING_PROVIDER=subprocess# Set the username for the index
export UV_INDEX_PRIVATE_REGISTRY_USERNAME=oauth2accesstoken
注意:可以使用tool.uv.keyring-provider
设置在您的 uv.toml
或 pyproject.toml
中启用密钥环。
同样,可以将索引的用户名直接添加到索引 URL 中。
将包发布到 Google Artifact Registry
如果您也想将您自己的包发布到 Google Artifact Registry,可以使用如构建和发布指南中所述的 uv publish
。
首先,将一个 publish-url
添加到您想要发布包的索引中。例如:
pyproject.toml
[[tool.uv.index]]
name = "private-registry"
url = "https://<REGION>-python.pkg.dev/<PROJECT>/<REPOSITORY>"
publish-url = "https://<REGION>-python.pkg.dev/<PROJECT>/<REPOSITORY>"
然后,配置凭据(如果未使用 keyring):
$ export UV_PUBLISH_USERNAME=oauth2accesstoken
$ export UV_PUBLISH_PASSWORD="$ARTIFACT_REGISTRY_TOKEN"
翻译后的 markdown 内容如下:
并且发布软件包:
uv publish --index private-registry
要使用 uv publish
而不将 publish-url
添加到项目中,您可以设置 UV_PUBLISH_URL
:
$ export UV_PUBLISH_URL=https://<REGION>-python.pkg.dev/<PROJECT>/<REPOSITORY>
$ uv publ.sh
注意,此方法不推荐,因为uv无法在上传工件之前检查该包是否已发布。
AWS CodeArtifact
uv 可以从 AWS CodeArtifact 安装软件包,要么通过使用访问令牌,要么使用 keyring
软件包。
注意:本指南假设已经安装并认证了awscli
。
索引可以这样声明:
pyproject.toml
[[tool.uv.index]]
name = "private-registry"
url = "https://<DOMAIN>-<ACCOUNT_ID>.d.codeartifact.<REGION>.amazonaws.com/pypi/<REPOSITORY>/simple/"
使用 AWS 访问令牌进行认证
凭据可以通过 “Basic” HTTP 认证方案提供。在 URL 的密码字段中包含访问令牌。用户名必须是 aws
,否则认证将失败。
使用 awscli
生成令牌:
export AWS_CODEARTIFACT_TOKEN="$(aws codeartifact get-authorization-token \--domain <DOMAIN> \--domain-owner <ACCOUNT_ID> \--query authorizationToken \--output text
)"
注意:您可能需要传递额外的参数以正确生成令牌(如 --region
),这是一个基本示例。
然后使用以下命令为索引设置凭据:
export UV_INDEX_PRIVATE_REGISTRY_USERNAME=aws
export UV_INDEX_PRIVATE_REGISTRY_PASSWORD="$AWS_CODEARTIFACT_TOKEN"
注意:PRIVATE_REGISTRY
应该与你在 pyproject.toml
中定义的索引名称匹配。
使用 keyring
和 keyrings.codeartifact
进行认证
您还可以使用 keyring
包以及 keyrings.codeartifact
plugin 对 Artifact Registry 进行认证。由于这两个包是认证到 Artifact Registry 所必需的,因此它们必须从除 Artifact Registry 之外的其他来源预先安装。
keyrings.codeartifact
插件封装了 boto3 以生成短期访问令牌,安全地将它们存储在系统密钥环中,并在它们过期时刷新它们。
uv 只支持在 子进程模式 下使用 keyring
包。keyring
可执行文件必须在 PATH
中,即全局安装或在活动环境中安装。keyring
CLI 需要在 URL 中包含用户名,并且它必须是 aws
。
# Pre-install keyring and AWS CodeArtifact plugin from the public PyPI
uv tool install keyring --with keyrings.codeartifact# Enable keyring authentication
export UV_KEYRING_PROVIDER=subprocess# Set the username for the index
export UV_INDEX_PRIVATE_REGISTRY_USERNAME=aws
注意:可以使用 tool.uv.keyring-provider
设置来在您的 uv.toml
或 pyproject.toml
中启用密钥环。
同样,索引的用户名可以直接添加到索引 URL 中。
将软件包发布到 AWS CodeArtifact
如果您还想将您自己的软件包发布到 AWS CodeArtifact,可以使用如构建和发布指南中描述的 uv publish
。
首先,将一个 publish-url
添加到您想要发布软件包的索引中。例如:
pyproject.toml
[[tool.uv.index]]
name = "private-registry"
url = "https://<DOMAIN>-<ACCOUNT_ID>.d.codeartifact.<REGION>.amazonaws.com/pypi/<REPOSITORY>/simple/"
publish-url = "https://<DOMAIN>-<ACCOUNT_ID>.d.codeartifact.<REGION>.amazonaws.com/pypi/<REPOSITORY>/"
然后,配置凭据(如果未使用keyring):
export UV_PUBLISH_USERNAME=aws
export UV_PUBLISH_PASSWORD="$AWS_CODEARTIFACT_TOKEN"
并且发布软件包:
uv publish --index private-registry
要使用 uv publish
而不将 publish-url
添加到项目中,您可以设置 UV_PUBLISH_URL
:
export UV_PUBLISH_URL=https://<DOMAIN>-<ACCOUNT_ID>.d.codeartifact.<REGION>.amazonaws.com/pypi/<REPOSITORY>/
uv publish
注意,此方法不推荐,因为uv无法在上传工件之前检查该软件包是否已经发布。
依赖项机器人
定期更新依赖项被认为是最佳实践,以避免暴露于漏洞中,限制依赖项之间的不兼容性,以及避免在从过旧版本升级时进行复杂的升级。各种工具可以帮助通过创建自动拉取请求来保持更新。其中一些支持 UV,或者正在进行支持 UV 的工作。
Renovate
uv 支持 Renovate.
注意:更新 uv pip compile
输出,如 requirements.txt
尚不支持。进度可在 renovatebot/renovate#30909 跟踪。
uv.lock
输出
Renovate 使用 uv.lock
文件的 presence 来确定是否使用 uv 来管理依赖项,并将建议升级 项目依赖项,可选依赖项 和 开发依赖项。Renovate 将更新 pyproject.toml
和 uv.lock
文件。
锁文件也可以通过启用 lockFileMaintenance
选项 来定期刷新(例如,以更新传递依赖项):
renovate.json5
{$schema: "https://docs.renovatebot.com/renovate-schema.json",lockFileMaintenance: {enabled: true,},
}
内联脚本元数据
Renovate 支持更新使用 脚本内联元数据 定义的依赖项。
由于它无法自动检测哪些 Python 文件使用脚本内联元数据,它们的位置需要使用 fileMatch
(fileMatch)显式定义,如下所示:
renovate.json5
{$schema: "https://docs.renovatebot.com/renovate-schema.json",pep723: {fileMatch: ["scripts/generate_docs.py","scripts/run_server.py",],},
}
使用 uv 与 AWS Lambda
AWS Lambda 是一种无服务器计算服务,允许您在不配置或管理服务器的情况下运行代码。
您可以使用 uv 与 AWS Lambda 管理您的 Python 依赖项,构建您的部署包,并部署您的 Lambda 函数。
提示:
查看 uv-aws-lambda-example 项目,了解使用 uv 将应用程序部署到 AWS Lambda 时的最佳实践示例。
入门
首先,假设我们有一个具有以下结构的最小 FastAPI 应用程序:
project
├── pyproject.toml
└── app├── __init__.py└── main.py
在 pyproject.toml
中包含:
pyproject.toml
[project]
name = "uv-aws-lambda-example"
version = "0.1.0"
requires-python = ">=3.13"
dependencies = [# FastAPI is a modern web framework for building APIs with Python."fastapi",# Mangum is a library that adapts ASGI applications to AWS Lambda and API Gateway."mangum",
][dependency-groups]
dev = [# In development mode, include the FastAPI development server."fastapi[standard]>=0.115",
]
并且 main.py
文件包含:
app/main.py
import loggingfrom fastapi import FastAPI
from mangum import Mangumlogger = logging.getLogger()
logger.setLevel(logging.INFO)app = FastAPI()
handler = Mangum(app)@app.get("/")
async def root() -> str:return "Hello, world!"
我们可以在本地上运行此应用程序:
uv run fastapi dev
从那里,在网页浏览器中打开 http://127.0.0.1:8000/ 将会显示 “Hello, world!”
部署 Docker 镜像
要将应用程序部署到 AWS Lambda,我们需要构建一个容器镜像,该镜像将应用程序代码和依赖项包含在单个输出目录中。
我们将遵循 Docker 指南(特别是多阶段构建)中概述的原则,以确保最终镜像尽可能小且缓存友好。
在第一阶段,我们将所有应用程序代码和依赖项填充到一个单独的目录中。在第二阶段,我们将这个目录复制到最终镜像中,省略构建工具和其他不必要的文件。
Dockerfile
FROM ghcr.io/astral-sh/uv:0.6.9 AS uv# First, bundle the dependencies into the task root.
FROM public.ecr.aws/lambda/python:3.13 AS builder# Enable bytecode compilation, to improve cold-start performance.
ENV UV_COMPILE_BYTECODE=1# Disable installer metadata, to create a deterministic layer.
ENV UV_NO_INSTALLER_METADATA=1# Enable copy mode to support bind mount caching.
ENV UV_LINK_MODE=copy# Bundle the dependencies into the Lambda task root via `uv pip install --target`.
#
# Omit any local packages (`--no-emit-workspace`) and development dependencies (`--no-dev`).
# This ensures that the Docker layer cache is only invalidated when the `pyproject.toml` or `uv.lock`
# files change, but remains robust to changes in the application code.
RUN --mount=from=uv,source=/uv,target=/bin/uv \--mount=type=cache,target=/root/.cache/uv \--mount=type=bind,source=uv.lock,target=uv.lock \--mount=type=bind,source=pyproject.toml,target=pyproject.toml \uv export --frozen --no-emit-workspace --no-dev --no-editable -o requirements.txt && \uv pip install -r requirements.txt --target "${LAMBDA_TASK_ROOT}"FROM public.ecr.aws/lambda/python:3.13# Copy the runtime dependencies from the builder stage.
COPY --from=builder ${LAMBDA_TASK_ROOT} ${LAMBDA_TASK_ROOT}# Copy the application code.
COPY ./app ${LAMBDA_TASK_ROOT}/app# Set the AWS Lambda handler.
CMD ["app.main.handler"]
Tip : 要将部署到基于ARM的AWS Lambda运行时,将 public.ecr.aws/lambda/python:3.13
替换为 public.ecr.aws/lambda/python:3.13-arm64
。
我们可以使用以下方法构建镜像,例如:
uv lock
docker build -t fastapi-app .
该 Dockerfile 结构的核心优势如下:
- 最小化镜像大小。 通过使用多阶段构建,我们可以确保最终镜像只包含应用程序代码和依赖项。例如,uv 二进制文件本身不包括在最终镜像中。
- 最大缓存重用。 通过将应用程序依赖项与应用程序代码分开安装,我们可以确保只有当依赖项发生变化时,Docker层缓存才会被无效化。
具体来说,在修改应用程序源代码后重新构建镜像可以重用缓存的层,从而实现毫秒级构建:
=> [internal] load build definition from Dockerfile 0.0s=> => transferring dockerfile: 1.31kB 0.0s=> [internal] load metadata for public.ecr.aws/lambda/python:3.13 0.3s=> [internal] load metadata for ghcr.io/astral-sh/uv:latest 0.3s=> [internal] load .dockerignore 0.0s=> => transferring context: 106B 0.0s=> [uv 1/1] FROM ghcr.io/astral-sh/uv:latest@sha256:ea61e006cfec0e8d81fae901ad703e09d2c6cf1aa58abcb6507d124b50286f 0.0s=> [builder 1/2] FROM public.ecr.aws/lambda/python:3.13@sha256:f5b51b377b80bd303fe8055084e2763336ea8920d12955b23ef 0.0s=> [internal] load build context 0.0s=> => transferring context: 185B 0.0s=> CACHED [builder 2/2] RUN --mount=from=uv,source=/uv,target=/bin/uv --mount=type=cache,target=/root/.cache/u 0.0s=> CACHED [stage-2 2/3] COPY --from=builder /var/task /var/task 0.0s=> CACHED [stage-2 3/3] COPY ./app /var/task 0.0s=> exporting to image 0.0s=> => exporting layers 0.0s=> => writing image sha256:6f8f9ef715a7cda466b677a9df4046ebbb90c8e88595242ade3b4771f547652d 0.0
在构建完成后,我们可以使用以下命令将镜像推送到 弹性容器注册库 (ECR):
aws ecr get-login-password --region region | docker login --username AWS --password-stdin aws_account_id.dkr.ecr.region.amazonaws.com
docker tag fastapi-app:latest aws_account_id.dkr.ecr.region.amazonaws.com/fastapi-app:latest
docker push aws_account_id.dkr.ecr.region.amazonaws.com/fastapi-app:latest
最后,我们可以使用 AWS 管理控制台或 AWS CLI 将镜像部署到 AWS Lambda,例如:
aws lambda create-function \--function-name myFunction \--package-type Image \--code ImageUri=aws_account_id.dkr.ecr.region.amazonaws.com/fastapi-app:latest \--role arn:aws:iam::111122223333:role/my-lambda-role
在哪里通过以下方式创建执行角色:执行角色
aws iam create-role \--role-name my-lambda-role \--assume-role-policy-document '{"Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": {"Service": "lambda.amazonaws.com"}, "Action": "sts:AssumeRole"}]}'
或者,使用以下方式更新现有函数:
aws lambda update-function-code \--function-name myFunction \--image-uri aws_account_id.dkr.ecr.region.amazonaws.com/fastapi-app:latest \--publish
要测试 Lambda,我们可以通过 AWS 管理控制台或 AWS CLI 调用它,例如:
aws lambda invoke \--function-name myFunction \--payload file://event.json \--cli-binary-format raw-in-base64-out \response.json
event.json
包含传递给 Lambda 函数的事件有效负载:
event.json
{"httpMethod": "GET","path": "/","requestContext": {},"version": "1.0"
}
并且 response.json
包含 Lambda 函数的响应:
response.json
{"statusCode": 200,"headers": {"content-length": "14","content-type": "application/json"},"multiValueHeaders": {},"body": "\"Hello, world!\"","isBase64Encoded": false
}
关于详细信息,请参阅AWS Lambda 文档。
工作区支持
如果一个项目包含本地依赖(例如,通过工作区,这些依赖也必须包含在部署包中。
我们将首先通过扩展上述示例来包含对本地开发的名为 library
的库的依赖。
首先,我们将创建这个库本身:
uv init --lib library
uv add ./library
运行 uv init
命令于 project
目录中,将自动将 project
转换为工作空间并将 library
添加为工作空间成员:
pyproject.toml
[project]
name = "uv-aws-lambda-example"
version = "0.1.0"
requires-python = ">=3.13"
dependencies = [# FastAPI is a modern web framework for building APIs with Python."fastapi",# A local library."library",# Mangum is a library that adapts ASGI applications to AWS Lambda and API Gateway."mangum",
][dependency-groups]
dev = [# In development mode, include the FastAPI development server."fastapi[standard]",
][tool.uv.workspace]
members = ["library"][tool.uv.sources]
lib = { workspace = true }
默认情况下,uv init --lib
将创建一个导出 hello
函数的包。我们将修改应用程序源代码以调用该函数:
app/main.py
import loggingfrom fastapi import FastAPI
from mangum import Mangumfrom library import hellologger = logging.getLogger()
logger.setLevel(logging.INFO)app = FastAPI()
handler = Mangum(app)@app.get("/")
async def root() -> str:return hello()
我们可以通过以下方式在本地运行修改后的应用程序:
uv run fastapi dev
确认在网页浏览器中打开 http://127.0.0.1:8000/ 显示 “Hello from library!”(而不是 “Hello, World!”)
最后,我们将更新Dockerfile以在部署包中包含本地库:
Dockerfile
FROM ghcr.io/astral-sh/uv:0.6.9 AS uv# First, bundle the dependencies into the task root.
FROM public.ecr.aws/lambda/python:3.13 AS builder# Enable bytecode compilation, to improve cold-start performance.
ENV UV_COMPILE_BYTECODE=1# Disable installer metadata, to create a deterministic layer.
ENV UV_NO_INSTALLER_METADATA=1# Enable copy mode to support bind mount caching.
ENV UV_LINK_MODE=copy# Bundle the dependencies into the Lambda task root via `uv pip install --target`.
#
# Omit any local packages (`--no-emit-workspace`) and development dependencies (`--no-dev`).
# This ensures that the Docker layer cache is only invalidated when the `pyproject.toml` or `uv.lock`
# files change, but remains robust to changes in the application code.
RUN --mount=from=uv,source=/uv,target=/bin/uv \--mount=type=cache,target=/root/.cache/uv \--mount=type=bind,source=uv.lock,target=uv.lock \--mount=type=bind,source=pyproject.toml,target=pyproject.toml \uv export --frozen --no-emit-workspace --no-dev --no-editable -o requirements.txt && \uv pip install -r requirements.txt --target "${LAMBDA_TASK_ROOT}"# If you have a workspace, copy it over and install it too.
#
# By omitting `--no-emit-workspace`, `library` will be copied into the task root. Using a separate
# `RUN` command ensures that all third-party dependencies are cached separately and remain
# robust to changes in the workspace.
RUN --mount=from=uv,source=/uv,target=/bin/uv \--mount=type=cache,target=/root/.cache/uv \--mount=type=bind,source=uv.lock,target=uv.lock \--mount=type=bind,source=pyproject.toml,target=pyproject.toml \--mount=type=bind,source=library,target=library \uv export --frozen --no-dev --no-editable -o requirements.txt && \uv pip install -r requirements.txt --target "${LAMBDA_TASK_ROOT}"FROM public.ecr.aws/lambda/python:3.13# Copy the runtime dependencies from the builder stage.
COPY --from=builder ${LAMBDA_TASK_ROOT} ${LAMBDA_TASK_ROOT}# Copy the application code.
COPY ./app ${LAMBDA_TASK_ROOT}/app# Set the AWS Lambda handler.
CMD ["app.main.handler"]
Tip : 要将应用程序部署到基于ARM的AWS Lambda运行时,请将 public.ecr.aws/lambda/python:3.13
替换为 public.ecr.aws/lambda/python:3.13-arm64
。
从那里,我们可以像之前一样构建和部署更新后的镜像。
部署 zip 存档
AWS Lambda 也支持通过 zip 存档进行部署。对于简单的应用程序,zip 存档可能比 Docker 镜像更直接、更高效的部署方法;然而,zip 存档的大小限制为 250 MB。
回到 FastAPI 的例子,我们可以通过以下方式将应用程序依赖项打包到本地目录以供 AWS Lambda 使用:
uv export --frozen --no-dev --no-editable -o requirements.txt
uv pip install \--no-installer-metadata \--no-compile-bytecode \--python-platform x86_64-manylinux2014 \--python 3.13 \--target packages \-r requirements.txt
提示:要将应用程序部署到基于ARM的AWS Lambda运行时,将 x86_64-manylinux2014
替换为 aarch64-manylinux2014
。
遵循AWS Lambda文档,我们然后可以将这些依赖打包成一个zip文件,如下所示:
cd packages
zip -r ../package.zip .
cd ..
最后,我们可以将应用程序代码添加到 zip 归档中:
zip -r package.zip app
我们可以通过 AWS 管理控制台或 AWS CLI 将 zip 存档部署到 AWS Lambda,例如:
aws lambda create-function \--function-name myFunction \--runtime python3.13 \--zip-file fileb://package.zip \--handler app.main.handler \--role arn:aws:iam::111122223333:role/service-role/my-lambda-role
在哪里通过以下方式创建执行角色:执行角色
aws iam create-role \--role-name my-lambda-role \--assume-role-policy-document '{"Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": {"Service": "lambda.amazonaws.com"}, "Action": "sts:AssumeRole"}]}'
或者,使用以下方式更新现有函数:
aws lambda update-function-code \--function-name myFunction \--zip-file fileb://package.zip
注意:默认情况下,AWS 管理控制台假定 Lambda 入口点为 lambda_function.lambda_handler
。如果您的应用程序使用不同的入口点,您需要在 AWS 管理控制台中修改它。例如,上面的 FastAPI 应用程序使用 app.main.handler
。
要测试 Lambda,我们可以通过 AWS 管理控制台或 AWS CLI 调用它,例如:
aws lambda invoke \--function-name myFunction \--payload file://event.json \--cli-binary-format raw-in-base64-out \response.json
{"StatusCode": 200,"ExecutedVersion": "$LATEST"
}
在 event.json
中包含要传递给 Lambda 函数的事件有效负载:
event.json
{"httpMethod": "GET","path": "/","requestContext": {},"version": "1.0"
}
并且 response.json
包含 Lambda 函数的响应:
response.json
{"statusCode": 200,"headers": {"content-length": "14","content-type": "application/json"},"multiValueHeaders": {},"body": "\"Hello, world!\"","isBase64Encoded": false
}
使用 Lambda 层
AWS Lambda 也支持在处理 zip 归档时部署多个组合的 Lambda 层。这些层在概念上类似于 Docker 镜像中的层,允许您将应用程序代码与依赖项分开。
特别是,我们可以为应用程序依赖项创建一个 lambda 层,并将其附加到 Lambda 函数中,而无需与应用程序代码本身分离。这种设置可以改善应用程序更新的冷启动性能,因为依赖项层可以在部署之间重用。
要创建 Lambda 层,我们将遵循类似的步骤,但创建两个单独的 zip 归档:一个用于应用程序代码,一个用于应用程序依赖项。
首先,我们将创建依赖项层。Lambda 层需要遵循略微不同的结构,因此我们将使用 --prefix
而不是 --target
:
uv export --frozen --no-dev --no-editable -o requirements.txt
uv pip install \--no-installer-metadata \--no-compile-bytecode \--python-platform x86_64-manylinux2014 \--python 3.13 \--prefix packages \-r requirements.txt
我们将按照 Lambda 层的预期布局压缩依赖项:
mkdir python
cp -r packages/lib python/
zip -r layer_content.zip python
Tip
要生成确定性的 zip 归档,请考虑在 zip
命令中传递 -X
标志以排除扩展属性和文件系统元数据。
并且发布 Lambda 层:
aws lambda publish-layer-version --layer-name dependencies-layer \--zip-file fileb://layer_content.zip \--compatible-runtimes python3.13 \--compatible-architectures "x86_64"
我们可以像上一个例子一样创建 Lambda 函数,省略依赖项:
# Zip the application code.
zip -r app.zip app# Create the Lambda function.
aws lambda create-function \--function-name myFunction \--runtime python3.13 \--zip-file fileb://app.zip \--handler app.main.handler \--role arn:aws:iam::111122223333:role/service-role/my-lambda-role
最后,我们可以使用由 publish-layer-version
步骤返回的 ARN 将依赖层附加到 Lambda 函数:
aws lambda update-function-configuration --function-name myFunction \--cli-binary-format raw-in-base64-out \--layers "arn:aws:lambda:region:111122223333:layer:dependencies-layer:1"
当应用程序依赖项发生变化时,可以通过重新发布层并更新 Lambda 函数配置来独立于应用程序更新层:
# Update the dependencies in the layer.
aws lambda publish-layer-version --layer-name dependencies-layer \--zip-file fileb://layer_content.zip \--compatible-runtimes python3.13 \--compatible-architectures "x86_64"# Update the Lambda function configuration.
aws lambda update-function-configuration --function-name myFunction \--cli-binary-format raw-in-base64-out \--layers "arn:aws:lambda:region:111122223333:layer:dependencies-layer:2"
2025-03-24(一)