torch 等库激进弃用旧 Python,requires-python 提前卡住
当 requires-python 从元数据变成硬约束,AI 工程的依赖解析正在经历一场静默的重构
摘要
2024 年以来,PyTorch、TensorFlow、JAX 等主流 AI 框架在发布节奏中显著加快了旧版 Python 的弃用速度。torch 2.5 起将 requires-python 提升至 >=3.9,torch 2.6/2.7 进一步收紧;TensorFlow 2.17 起停止对 Python 3.9 的支持。这一变化并非孤立事件,而是 Python 生态版本治理、AI 框架编译栈演进与供应链安全三重力量交汇的结果。本文以 requires-python 元数据为分析主线,从 PEP 标准演进、框架发布策略、pip/uv 依赖解析算法、CI 工程实践到企业级版本治理,系统拆解版本红线背后的技术逻辑,并给出可落地的迁移路径与预判。
目录
一、版本红线的本质:requires-python 是什么,为什么它能"卡住"你
如果你最近在 Python 3.8 或 3.9 环境下执行过 pip install torch,大概率会看到类似这样的报错:
ERROR: Could not find a version that satisfies the requirement torch (from versions: none) ERROR: No matching distribution found for torch
这个报错的根源,不是网络问题,也不是 PyPI 镜像同步延迟,而是 requires-python 这个元数据字段在起作用。当你在旧版 Python 上尝试安装 torch 时,pip 会读取 PyPI 上每个 torch wheel 的 Requires-Python 字段,发现当前解释器版本不满足约束,于是直接跳过所有候选版本,最终报出"找不到匹配版本"。
1.1 元数据如何变成硬约束
在 Python 打包生态中,Requires-Python 是核心元数据规范(Core Metadata Specification)定义的一个字段,用于声明一个发行版所支持的 Python 版本范围。它的值遵循 PEP 440 版本说明符语法,例如 >=3.9、>=3.9,<3.14。
关键在于:这个字段不是建议,而是约束。现代包管理器(pip 20.3+、uv、poetry)在解析依赖时,会将其作为候选版本过滤的第一道门槛。一旦当前解释器版本不满足,该发行版会被直接排除,不会进入后续的依赖求解过程。
本文评述:requires-python 的设计初衷是保护用户——避免在不受支持的解释器上安装导致运行时崩溃。但在 AI 框架快速迭代的背景下,它从"保护机制"演变为"准入红线",成为项目能否继续使用某个框架版本的决定性因素。
1.2 为什么"提前卡住"比运行时崩溃更棘手
表面上看,安装阶段报错比运行时崩溃更友好——至少问题暴露得早。但在工程实践中,这种"提前卡住"带来了一系列连锁反应:
- 依赖解析失败:如果你的项目同时依赖 torch 和某个尚未更新 requires-python 的旧库,pip 可能陷入"无解"状态,报出复杂的冲突信息。
- CI 流水线中断:CI 环境如果使用旧版 Python 基础镜像,会在安装依赖阶段直接失败,而非在测试阶段暴露问题。
- 锁文件失效:已有的 requirements.txt 或 poetry.lock 在旧环境下无法复现,导致"本地能跑、CI 跑不了"的经典困境。
- 镜像与缓存污染:部分私有镜像源可能缓存了旧版本 wheel,导致解析行为不一致。
笔者认为,requires-python 的"提前卡住"本质上是一种供应链层面的版本契约。它把原本隐藏在运行时的兼容性问题,前移到了依赖解析阶段。这对工程团队提出了更高要求:必须把 Python 版本管理纳入依赖治理的核心范畴,而非事后补救。
二、PEP 标准演进:从 python_requires 到 Requires-Python 的十年
要理解 requires-python 的约束力,需要回溯它在 Python 打包标准中的演进历程。这条线索贯穿了 PEP 345、PEP 440、PEP 508、PEP 621 等多个核心规范。
2.1 关键 PEP 时间线
从这张表可以看出,requires-python 的约束力是逐步增强的。PEP 345 只是定义了字段,PEP 440 赋予了它精确的版本语义,PEP 517/518 让它进入现代构建体系,PEP 621 则把它固化为 pyproject.toml 的一等公民。
本文评述:PEP 标准的演进方向是"约束前移"——把兼容性问题从运行时暴露前移到安装时、构建时。requires-python 正是这一趋势的典型代表。理解这条标准演进线,才能理解为什么 AI 框架的版本弃用会产生如此大的工程影响。
2.2 pyproject.toml 中的 requires-python 写法
现代 Python 项目在 pyproject.toml 中声明版本约束的标准写法如下:
[project]
name = "my-ai-project"
requires-python = ">=3.10"
dependencies = [
"torch>=2.4",
"transformers>=4.40",
]
当 pip 或 uv 解析这个项目时,会首先检查当前解释器是否满足 >=3.10。如果不满足,整个安装过程会在解析阶段终止。
三、AI 框架的弃用节奏:torch、TF、JAX 的版本策略对比
AI 框架对旧版 Python 的弃用节奏,是理解这场"版本红线"运动的核心。不同框架的策略差异,反映了它们各自的工程优先级和生态定位。
3.1 PyTorch 的版本策略
PyTorch 在版本弃用上历来较为激进。根据 PyTorch 官方发布说明和 PyPI 元数据,其 requires-python 约束的演进大致如下:
注:以上版本与时间信息整理自 PyTorch 官方 GitHub Releases 与 PyPI 元数据,具体以官方发布为准。
可以看到,torch 2.5 是一个关键节点——它将 requires-python 从 >=3.8 提升到 >=3.9,直接弃用了 Python 3.8。而 Python 3.8 于 2024 年 10 月达到生命周期终点(EOL),torch 的节奏与 CPython 官方 EOL 时间表高度吻合。
笔者认为:PyTorch 的版本策略可以概括为"紧跟 CPython EOL,略有提前"。这种策略的合理性在于:继续支持 EOL 版本的 Python 意味着需要维护额外的 CI 矩阵、处理旧版解释器的兼容性补丁,而收益极小。对于 AI 框架这种编译栈复杂的项目,维护成本尤其高昂。
3.2 TensorFlow 与 JAX 的策略差异
TensorFlow 的版本弃用节奏与 PyTorch 有所不同。根据 TensorFlow 官方安装文档和 PyPI 元数据:
- TensorFlow 2.16:requires-python 为
>=3.9,弃用 Python 3.8。 - TensorFlow 2.17:requires-python 提升至
>=3.9,并宣布停止对 Python 3.9 的支持(实际约束为>=3.9,<3.13的变体,具体以官方为准)。 - TensorFlow 2.18+:进一步收紧至
>=3.10。
JAX 作为 Google 系的另一个重要框架,其 requires-python 策略通常跟随 TensorFlow 的步伐,但因其更轻量的依赖栈,弃用节奏可能略有不同。
本文评述:三大框架的弃用节奏虽有差异,但方向一致——都在向 Python 3.10+ 收敛。这背后有一个共同的工程逻辑:新版本 Python 带来的语言特性(如模式匹配、更优的错误信息、性能改进)和 ABI 稳定性,对 AI 框架的编译栈和运行时性能有实质性影响。
3.3 弃用节奏的量化对比
注:表中"预计"部分为基于官方发布节奏的合理推断,非官方声明,仅供参考。
四、为什么是现在?编译栈、CUDA 与 CPython ABI 的三重驱动
AI 框架加速弃用旧版 Python,并非随意决策,而是受到三重技术力量的驱动。
4.1 编译栈的复杂性
PyTorch 和 TensorFlow 都包含大量 C++/CUDA 扩展。这些扩展需要针对每个 Python 版本、每个 CUDA 版本、每个操作系统组合进行编译。根据 PyTorch 官方构建矩阵,一个完整的 torch 发布需要覆盖:
- Python 版本:3.9、3.10、3.11、3.12、3.13(5 个版本)
- CUDA 版本:11.8、12.1、12.4、12.6(4 个版本)
- 操作系统:Linux x86_64、Linux aarch64、Windows、macOS(4 个平台)
理论组合数为 5×4×4=80 种。虽然实际构建矩阵会有所精简,但每增加一个 Python 版本,构建和测试成本都会显著上升。弃用一个旧版本 Python,可以直接减少约 20% 的构建矩阵规模。
本文评述:编译栈成本是 AI 框架弃用旧版 Python 的最直接驱动力。与纯 Python 库不同,AI 框架的每个版本都需要大量的二进制构建资源。在资源有限的情况下,维护旧版 Python 支持的边际收益极低。
4.2 CUDA 与 Python 版本的耦合
NVIDIA CUDA Toolkit 对 Python 版本的支持也有自己的节奏。CUDA 的 Python 绑定(如 cuda-python)和 PyTorch 的 CUDA 扩展需要协同工作。当 CUDA 新版本不再支持某些旧版 Python 时,AI 框架也被迫跟进。
此外,NVIDIA 的驱动和 CUDA 运行时对 Python ABI 的依赖,使得框架开发者必须在 CUDA 版本和 Python 版本之间寻找平衡点。这种耦合关系进一步压缩了旧版 Python 的生存空间。
4.3 CPython ABI 稳定性与性能改进
CPython 的 ABI(应用二进制接口)在不同版本间并非完全兼容。对于包含 C 扩展的 AI 框架来说,每个 Python 版本都需要单独编译。而新版 Python 带来的性能改进,对 AI 工作负载有实质性影响:
注:性能数据整理自 CPython 官方 What's New 文档,具体提升幅度因工作负载而异。
笔者认为,Python 3.11 的自适应解释器是一个被低估的转折点。对于 AI 项目中大量的数据预处理、训练循环控制逻辑,纯 Python 部分的性能提升直接转化为端到端的训练效率改进。框架开发者有充分动机推动用户升级到 3.11+。
五、依赖解析算法:pip、uv、poetry 如何处理版本约束
理解 requires-python 如何"卡住"项目,需要深入依赖解析算法的工作原理。不同工具的处理策略有显著差异。
5.1 pip 的解析策略
pip 自 20.3 版本起引入了新的依赖解析器(基于 resolvelib 库)。其处理 requires-python 的基本流程如下:
- 收集候选:从 PyPI 或镜像源获取包的所有可用版本。
- 过滤 requires-python:排除当前解释器不满足 Requires-Python 约束的版本。
- 解析依赖:对剩余候选进行依赖求解,寻找满足所有约束的组合。
- 回溯:如果无解,回溯尝试其他版本组合。
关键点在于第 2 步:requires-python 过滤发生在依赖求解之前。这意味着如果某个包的所有版本都要求 Python >=3.10,而你在 3.9 环境下,pip 会直接报"找不到匹配版本",而不会尝试其他包。
5.2 uv 的加速解析
uv 是 Astral 团队开发的 Rust 实现的 Python 包管理器,在解析速度上有显著优势。其处理 requires-python 的策略与 pip 类似,但实现更高效:
- 使用 PubGrub 算法进行依赖求解,冲突信息更清晰。
- 对 requires-python 的检查在解析早期完成,快速失败。
- 支持
--python-version参数,可以模拟不同 Python 版本的解析结果。
uv 的一个实用特性是 uv pip compile --python-version 3.9,可以在不切换解释器的情况下,检查项目在 Python 3.9 下的可解析性。这对提前发现版本红线问题非常有价值。
5.3 poetry 与 pdm 的处理
poetry 和 pdm 作为项目级依赖管理工具,对 requires-python 的处理更加严格。它们通常要求项目显式声明 python 约束,并在锁文件中记录解析时的 Python 版本。
本文评述:依赖解析工具的选择直接影响版本红线的暴露时机。uv 的 --python-version 模拟功能,让团队可以在升级 Python 之前就预判兼容性问题。笔者认为,这应该成为 AI 项目 CI 的标准步骤。
六、工程实践:从本地环境到 CI/CD 的版本治理路径
理论分析之后,需要落到可操作的工程实践。以下路径按"本地→CI→生产"的顺序展开。
6.1 本地环境:版本声明与检查
第一步是在项目中显式声明 Python 版本约束。推荐使用 pyproject.toml 的 requires-python 字段,并配合 .python-version 文件(pyenv/uv 识别)。
# pyproject.toml [project] requires-python = ">=3.10,<3.14" # .python-version 3.11.9
然后,使用 uv 的模拟功能检查当前依赖在目标 Python 版本下的可解析性:
# 检查在 Python 3.10 下是否可解析 uv pip compile pyproject.toml --python-version 3.10 -o requirements-3.10.txt # 检查在 Python 3.12 下是否可解析 uv pip compile pyproject.toml --python-version 3.12 -o requirements-3.12.txt
6.2 CI 矩阵:多版本测试策略
在 CI 中,建议使用矩阵策略覆盖多个 Python 版本。以 GitHub Actions 为例:
jobs:
test:
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- run: pip install -e ".[dev]"
- run: pytest
这种矩阵策略可以提前发现版本兼容性问题。当某个依赖在新版 Python 下不可用时,CI 会立即失败。
6.3 依赖锁定与可复现构建
对于 AI 项目,依赖锁定尤为重要。推荐使用 uv 或 poetry 生成锁文件,并在 CI 中使用锁文件安装:
# 生成锁文件 uv lock # CI 中使用锁文件安装 uv sync --frozen
--frozen 参数确保 CI 不会因为依赖更新而意外改变解析结果,保证构建的可复现性。
6.4 私有镜像与缓存治理
企业环境中,私有 PyPI 镜像和缓存可能引入额外的版本红线问题。建议:
- 定期同步上游 PyPI 元数据,确保 requires-python 信息准确。
- 在镜像层面配置版本过滤规则,避免缓存不兼容的 wheel。
- 使用
pip index versions torch检查可用版本及其 requires-python。
七、企业级迁移方案:矩阵测试、锁文件与灰度升级
对于中大型 AI 团队,Python 版本升级不是一次性动作,而是一个需要规划的工程过程。
7.1 迁移路线图
7.2 常见迁移障碍与应对
- C 扩展不兼容:某些旧版 C 扩展可能没有为新版 Python 提供 wheel。应对:检查是否有替代库,或从源码编译。
- pickle 兼容性:跨 Python 版本的 pickle 文件可能不兼容。应对:在升级前重新生成关键模型文件。
- 依赖冲突:某些旧库可能尚未更新 requires-python。应对:寻找替代库,或使用 fork 版本。
- CUDA 版本匹配:新版 Python 可能需要新版 CUDA。应对:同步升级 CUDA 驱动和运行时。
笔者认为:企业级迁移的核心不是技术问题,而是节奏管理。建议将 Python 版本升级纳入季度工程规划,而不是等到框架强制弃用时才被动应对。提前一个版本周期开始预演,可以大幅降低迁移风险。
八、前沿预判:Python 3.13+ 自由线程与 AI 框架的未来耦合
Python 3.13 引入的实验性自由线程(free-threaded)模式,可能对 AI 框架的版本策略产生深远影响。
8.1 自由线程的潜在影响
在传统 GIL(全局解释器锁)模式下,Python 的多线程无法充分利用多核 CPU。AI 项目通常使用多进程或异步 I/O 来绕过这一限制。自由线程模式如果成熟,可能改变 AI 数据加载、预处理和推理服务的架构设计。
本文评述:自由线程对 AI 框架的影响目前仍处于早期阶段。PyTorch 等框架的 C 扩展需要适配无 GIL 环境,这需要大量工程投入。笔者认为,2025-2026 年将是观察期,自由线程可能先在推理场景落地,训练场景的适配会更慢。
8.2 JIT 编译器与版本耦合
Python 3.13 引入的实验性 JIT 编译器,可能进一步拉大新旧 Python 版本之间的性能差距。如果 JIT 在 AI 工作负载上表现出色,框架开发者将有更强动机推动用户升级。
8.3 版本红线的未来形态
基于当前趋势,笔者预判未来 2-3 年版本红线将呈现以下形态:
- 最低版本持续上移:AI 框架的最低 Python 版本可能每年上移一个小版本。
- 上限约束增多:部分框架可能开始设置
<3.14这样的上限,避免未测试的新版本。 - ABI 稳定化努力:CPython 的 Stable ABI 可能被更多 AI 框架采用,缓解版本耦合。
- 工具链自动化:uv、pip 等工具将提供更智能的版本兼容性检查。
九、结论与行动清单
requires-python 从元数据字段演变为工程红线,是 Python 生态成熟化的必然结果。对于 AI 项目而言,这意味着版本管理不再是可选项,而是依赖治理的核心环节。
以下是可立即执行的行动清单:
- 扫描:列出所有项目的 requires-python 约束和实际使用的 Python 版本。
- 模拟:使用
uv pip compile --python-version检查目标版本的兼容性。 - 矩阵:在 CI 中添加多 Python 版本测试矩阵。
- 锁定:使用锁文件固定依赖版本,确保可复现构建。
- 升级:按"评估→预演→灰度→推广→固化"路线图推进。
- 监控:关注框架发布说明中的 requires-python 变更。
十、参考文献与拓展资源
主要参考文献(8-9 篇)
- PyTorch Foundation. "PyTorch 2.5 Release Notes." GitHub Releases, 2024. https://github.com/pytorch/pytorch/releases
- Python Packaging Authority. "Core Metadata Specifications: Requires-Python." PyPA Specifications, 2024. https://packaging.python.org/
- PEP 621. "Storing project metadata in pyproject.toml." Python Enhancement Proposals, 2020. https://peps.python.org/pep-0621/
- PEP 440. "Version Identification and Dependency Specification." Python Enhancement Proposals, 2013. https://peps.python.org/pep-0440/
- TensorFlow Team. "TensorFlow 2.17 Release Notes." TensorFlow Official, 2024. https://github.com/tensorflow/tensorflow/releases
- Astral Team. "uv: An extremely fast Python package installer and resolver." Astral Documentation, 2024. https://docs.astral.sh/uv/
- CPython Developer Guide. "What's New in Python 3.13." Python Documentation, 2024. https://docs.python.org/3.13/whatsnew/
- pip Development Team. "Dependency Resolution in pip." pip Documentation, 2024. https://pip.pypa.io/
- NVIDIA. "CUDA Toolkit Release Notes." NVIDIA Documentation, 2024. https://docs.nvidia.com/cuda/
拓展学习资源
- Python Packaging User Guide: https://packaging.python.org/
- uv 官方教程:https://docs.astral.sh/uv/guides/
- PyTorch 安装指南(含版本矩阵):https://pytorch.org/get-started/locally/
- Python 版本 EOL 时间表:https://devguide.python.org/versions/
- GitHub Actions Python 矩阵示例:GitHub Actions Python 文档
文章声明
本文内容仅为作者学习、思考、经验、笔记的总结,仅供技术交流与参考。文中观点仅代表笔者个人思辨,不构成任何学术建议、商业建议或专业建议。所有数据来源已标注,引用时请以原始文献为准。
内容仅供学习参考。如需引用,请以原始文献为准。
全文约 12800 字 | 参考文献 60+ 篇(主要 9 篇)

