可复现示例
为什么可复现示例很重要
最小可复现示例 (MRE) 对于修复 Bug 至关重要。如果没有一个可以用来复现问题的示例,维护者将无法进行调试或测试问题是否已修复。如果示例不是最小化的(即包含大量与问题无关的内容),维护者可能需要花费更长的时间来识别问题的根本原因。
如何编写可复现示例
在编写可复现示例时,目标是提供他人复现你的示例所需的所有上下文。这包括:
- 你正在使用的平台(例如,操作系统和架构)
- 任何相关的系统状态(例如,明确设置的环境变量)
- uv 的版本
- 其他相关工具的版本
- 相关文件(
uv.lock、pyproject.toml等) - 要运行的命令
为确保你的复现是最小化的,请移除尽可能多的依赖项、设置和文件。请务必在分享之前测试你的复现方案。我们建议在复现中包含详细日志(verbose logs);它们在你的机器上可能会以关键的方式表现不同。对于非常长的日志,使用 Gist 会很有帮助。
下面,我们将介绍几种用于创建和分享可复现示例的具体策略。
提示
Stack Overflow 上有一份关于创建 MRE 基础知识的优秀指南。
可复现示例的策略
Docker 镜像
编写 Docker 镜像通常是分享可复现示例的最佳方式,因为它完全自包含。这意味着复现者系统的状态不会影响该问题。
注意
仅当问题在 Linux 上可复现时,使用 Docker 镜像才可行。当使用 macOS 时,请务必确认你的镜像是否无法在 Linux 上复现,因为某些 Bug 确实是特定于操作系统的。虽然使用 Docker 运行 Windows 容器是可行的,但这并不常见。这类 Bug 通常建议以脚本形式报告。
当使用 uv 编写 Docker MRE 时,最好从 uv 的 Docker 镜像之一开始。这样做时,请确保固定到特定的 uv 版本。
虽然 Docker 镜像与系统隔离,但构建默认会使用你系统的架构。在分享复现方案时,你可以显式设置平台,以确保复现者获得预期的行为。uv 发布了适用于 linux/amd64(例如 Intel 或 AMD)和 linux/arm64(例如 Apple M 系列或 ARM)的镜像。
Docker 镜像最适合用于复现可以通过命令构建的问题,例如:
FROM --platform=linux/amd64 ghcr.io/astral-sh/uv:0.5.24-debian-slim
RUN uv init /mre
WORKDIR /mre
RUN uv add pydantic
RUN uv sync
RUN uv run -v python -c "import pydantic"
不过,你也可以直接在镜像中内联写入文件:
FROM --platform=linux/amd64 ghcr.io/astral-sh/uv:0.5.24-debian-slim
COPY <<EOF /mre/pyproject.toml
[project]
name = "example"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = ["pydantic"]
EOF
WORKDIR /mre
RUN uv lock
如果你需要写入多个文件,最好创建并发布一个 Git 仓库。你可以结合这些方法,并在仓库中包含一个 Dockerfile。
分享 Docker 复现方案时,包含构建日志会很有帮助。你可以通过禁用缓存和精简输出功能来查看构建步骤的更多输出信息:
脚本
当报告无法在容器中复现的特定于平台的 Bug 时,最佳实践是包含一个显示可用于复现该 Bug 的命令的脚本,例如:
如果你的复现需要多个文件,请使用 Git 仓库来分享它们。
除了脚本外,请包含失败过程的详细日志(即使用 -v 标志)以及完整的错误信息。
每当脚本依赖于外部状态时,请务必分享该信息。例如,如果你是在 Windows 上编写的脚本,且它使用了你通过 choco 安装的 Python 版本并运行在 PowerShell 6.2 上,请将其包含在报告中。
Git 仓库
在分享 Git 仓库复现方案时,请包含一个可以复现问题的脚本,或者更好的是,包含一个 Dockerfile。脚本的第一步应该是克隆仓库并检出特定的提交:
$ git clone https://github.com/<user>/<project>.git
$ cd <project>
$ git checkout <commit>
$ <commands to produce error>
你可以在 GitHub UI 中或使用 gh CLI 快速创建一个新仓库。
使用 Git 仓库进行复现时,请记住通过排除不需要的文件或设置来最小化内容,以复现你的问题。