一句话结论
Python 3.15 用户若遇到 uv.lock 锁定旧版本依赖导致的构建报错,删除该文件并重新运行命令即可解决。
关键要点
- uv 运行测试或脚本时会自动生成 uv.lock,但库项目通常将其列入 .gitignore 避免影响下游用户。
- 报错案例中 watchfiles 1.1.1 依赖 PyO3,而 PyO3 当前最大支持 Python 3.14,与 3.15 不匹配。
- 删除本地 uv.lock 后重新执行 uv run pytest,uv 会基于 Python 3.15 环境重新解析并锁定可用版本。
- Python 3.10 已被弃用,目前主流可用版本为 3.11 及以上,3.15 为当前最新开发主线。
- 库项目不应将 uv.lock 提交至仓库,避免强制下游用户锁定特定依赖版本。
背景与事实
Simon Willison 于 2026 年 11 月 1 日记录,其在全面切换至 Python 3.15 后,间歇性遭遇 Python 依赖构建错误。其多数项目为库代码,遵循“库不锁定依赖版本”的惯例,因此不提交 uv.lock 文件;但在本地运行 uv run pytest 等命令时,uv 仍会在项目目录生成 uv.lock 并写入 .gitignore,不进入版本控制。问题根源在于:uv.lock 曾锁定某依赖版本,而该版本的构建工具链(如 PyO3)尚未适配 Python 3.15。具体案例中,watchfiles 1.1.1 的构建依赖 maturin 调用 PyO3,而 PyO3 声明的最大支持版本为 3.14,导致在 3.15 解释器下 maturin.build_wheel 失败。Willison 发现,直接删除本地 uv.lock 文件并重新运行 uv run pytest,uv 会跳过旧的版本锁定,重新解析依赖图并选择或构建与 Python 3.15 兼容的版本,错误随之消失。其同月早些时候发布的另一篇博文《Hello Python 3.15, goodbye 3.10, and now I can use 3.11》亦提及 Python 3.10 的终止与 3.15 的采用,与本次问题背景一致。
影响分析
(分析判断)对中文开发者而言,若已在 2026 年切换至 Python 3.15,本地 uv.lock 文件成为高频排障点。实际影响是:库项目开发者需养成“uv run 生成 lock 后不提交、报错即删锁重跑”的本地工作流;应用项目若提交了 uv.lock,则应在升级解释器后主动删除并重新锁定,避免 CI 流水线因旧 lock 中版本与 3.15 不兼容而中断。对于 PyO3、maturin 等 Rust-Python 桥接生态,在官方适配 3.15 前的过渡期,版本锁定文件是主要冲突面,团队可在预提交钩子中增加 lock 文件与解释器版本的校验提示。
适用边界
该结论仅在“uv 管理 Python 环境、且项目采用 Python 3.15 解释器”的条件下成立。不适用的场景包括:项目锁定了必须固定版本的 CVE 缓解策略、CI 环境中 uv.lock 由流水线统一生成并校验哈希、依赖本身在源码级别完全不支持 3.15(此时删锁无效,需等待上游发版);以及使用 poetry、pip 等传统管理器的项目,其 lock 文件删除逻辑与 uv 行为不同。
孤本观察
(编辑判断)Willison 将“删 uv.lock”提炼为一条可复述的短规则,本质是 uv 设计哲学中“lock 文件为本地缓存而非契约”的具象化;对中文社区而言,把这条规则直接写进团队 Python 3.15 迁移手册的排障章节,比复述完整依赖解析原理更具操作性。
常见问题
导致 Python 3.15 环境下构建失败的具体依赖链条是什么?
watchfiles 1.1.1 依赖 PyO3,而 PyO3 当前最大支持 Python 3.14,与 3.15 不匹配,导致 maturin 构建 wheel 失败。
如何快速解决由 uv.lock 导致的 Python 3.15 构建错误?
直接删除本地的 uv.lock 文件,并重新运行 uv run pytest,uv 会重新解析并锁定兼容 Python 3.15 的依赖版本。
删除 uv.lock 修复方法不适用于哪些特定场景?
项目锁定了固定版本的 CVE 缓解策略、CI 中由流水线统一生成并校验哈希的 lock 文件、依赖源码不支持 3.15,以及使用 poetry 或 pip 的项目。
库项目为何通常建议不将 uv.lock 提交至版本控制仓库?
为避免强制下游用户锁定特定依赖版本,库项目通常将 uv.lock 列入 .gitignore,保持依赖灵活性。