Python 版本生命周期
Python 的版本不是「发布即永久维护」,每条 3.X 产品线都有明确的支持窗口:一段完整支持期,之后是一段仅安全修复期,最后进入生命周期终点(end-of-life, EOL)。理解这套时间表,才能判断手里的版本还能安全使用多久、什么时候必须升级。
前置知识
阅读本节前,建议先了解:版本选择策略
基础概念
Python 官方开发者指南(Python Developer's Guide)把每个版本的状态划分为五个阶段。这套规则由 PEP 602 定义:
| 阶段 | 英文 | 含义 |
|---|---|---|
| 特性开发 | feature | 分支接受新特性、缺陷修复与安全修复 |
| 预发布 | prerelease | 首个 beta 之后,不再接受新特性,只接受修复 |
| 缺陷修复 | bugfix | 版本正式发布后的完整支持期,定期发布含安装包的补丁 |
| 安全修复 | security | 仅接受安全修复,只发布源码版,不提供安装包 |
| 生命周期结束 | end-of-life | 不再接受任何修复,版本彻底停止维护 |
关键时间尺度(自 Python 3.13 起):
- 完整支持期 2 年:约每两个月发布一个补丁版,同时提供 Windows/macOS 安装包。
- 安全支持期 3 年:仅在有安全问题时发布源码版,没有固定节奏,也不再提供安装包。
- 总生命周期 5 年:从
3.X.0正式发布算起,满 5 年后 EOL。
一个常见的误解是「EOL 只是不再加新功能」。实际上 EOL 意味着连安全漏洞都不再修复,继续使用会把已知漏洞长期暴露在生产环境。
语法与用法
查看本机版本与状态是最基本的操作。
# 查看解释器版本
python3 --version
# Python 3.13.1
# 查看更详细的版本与构建信息
python3 -VV
# Python 3.13.1 (main, Dec 3 2024, 10:00:00) [Clang 16.0.0]
# macOS 自带 Python 通常是系统工具依赖的版本,不要直接升级
/usr/bin/python3 --version在代码里判断版本,用于条件分支:
import sys
# sys.version_info 是可比较的命名元组
if sys.version_info >= (3, 12):
print("支持 PEP 695 类型参数语法")
else:
print("请升级到 3.12 及以上")
# 完整版本字符串
print(sys.version)
# 3.13.1 (main, Dec 3 2024, 10:00:00) [Clang 16.0.0]
# 仅版本号
print(sys.version_info[:3])
# (3, 13, 1)通过版本管理器查看与切换:
# pyenv:列出本机已安装版本,* 表示当前生效
pyenv versions
# 安装受支持的新版本
pyenv install 3.13.1
# uv:查看已安装与可安装版本
uv python list
# 查看某个版本是否仍在维护(需要联网)
# 官方表格:https://devguide.python.org/versions/详细说明
PEP 602:年度发布节奏
在 PEP 602 之前,Python 的发布节奏并不固定(约 18 个月一次)。PEP 602 从 Python 3.9 开始确立「每年 10 月发布一个特性版本」的节奏:
| 阶段 | 时长 | 说明 |
|---|---|---|
| 与上一版本重叠的开发 | 约 5 个月 | 上一版本处于 beta/rc,新版本并行开发 |
| alpha 阶段 | 约 7 个月 | 新特性增量合入,同时修 bug |
| beta 阶段 | 约 3 个月 | 共 4 个 beta,冻结新特性 |
| rc 阶段 | 约 2 个月 | 发布候选版,只修严重问题 |
| 合计 | 约 17 个月 | 最终形成 12 个月的发布间隔 |
「17 个月开发、12 个月间隔」的差值来自重叠期。这种安排让每年 10 月都有一个可预期的新版本,方便下游生态规划适配。
各支持阶段的实务含义
| 阶段 | 你能得到什么 | 你需要做什么 |
|---|---|---|
| feature | 新特性、bug 修复、安全修复 | 可尝试,但不适合生产 |
| prerelease | 新特性的最终打磨与修复 | 用于提前测试依赖兼容性 |
| bugfix | 定期补丁 + 官方安装包 | 生产环境的主要选择窗口 |
| security | 仅安全补丁(源码) | 规划升级,避免停留在该阶段过久 |
| end-of-life | 无 | 必须升级,尤其是公网服务 |
处于 security 阶段时,若遇到非安全类 bug,官方不会修复;你只能在更高版本中寻找已修复的对应实现,或自行打补丁。
支持时间线的变化:3.12 与 3.13 的分界
PEP 602 在 2024 年被修订,把新版本的完整支持期从 1.5 年延长到 2 年:
- Python 3.9 ~ 3.12:完整支持 1.5 年,之后 3.5 年安全修复,共 5 年。
- Python 3.13 及以后:完整支持 2 年,之后 3 年安全修复,共 5 年。
所以 3.13 的「bugfix」阶段比 3.12 长半年。这个改动对下游是利好:有更多时间在获得官方安装包的状态下完成适配。
官方版本状态表
下表依据官方开发者指南整理(日期可能随实际发布微调):
| 版本 | 状态 | 首次发布 | 计划 EOL | 发布计划 |
|---|---|---|---|---|
| 3.15 | prerelease | 2026-10(计划) | 2031-10 | PEP 790 |
| 3.14 | bugfix | 2025-10-07 | 2030-10 | PEP 745 |
| 3.13 | bugfix | 2024-10-07 | 2029-10 | PEP 719 |
| 3.12 | security | 2023-10-02 | 2028-10 | PEP 693 |
| 3.11 | security | 2022-10-24 | 2027-10 | PEP 664 |
| 3.10 | end-of-life | 2021-10-04 | 2026-10-01 | PEP 619 |
| 3.9 | end-of-life | 2020-10-05 | 2025-10-31 | PEP 596 |
| 3.8 | end-of-life | 2019-10-14 | 2024-10-07 | PEP 569 |
几点解读:
- 3.10 是最近刚进入 EOL 的版本,最后一个版本为 3.10.22。
- 3.11 与 3.12 处于 security 阶段,仅会收到安全修复。
- 3.13 与 3.14 处于 bugfix 阶段,是当前生产环境较优的选择。
- 3.15 尚在预发布,官方计划 2026 年 10 月发布正式版。
提示:具体日期以 devguide.python.org/versions 为准,本文表格仅作参考。
预发布阶段的命名规则
预发布版本遵循 PEP 440 的命名约定,安装器默认不会选中它们:
| 后缀 | 含义 | 示例 |
|---|---|---|
aN | alpha,第 N 个 alpha | 3.15.0a1 |
bN | beta,第 N 个 beta,特性冻结 | 3.15.0b1 |
rcN | release candidate,发布候选 | 3.15.0rc1 |
从 beta 1 起不再合入新特性,因此 beta 阶段是「验证依赖是否兼容下一版本」的最佳窗口。若你的库想在 3.15 正式发布当天即可用,就应在 beta 阶段开始测试。
安全修复的边界
进入 security 阶段的版本,官方只做以下事情:
- 修复被评定为安全问题(通常涉及 CVE)的缺陷;
- 修复构建相关的严重问题;
- 以源码形式发布,不再提供 Windows/macOS 安装包。
这意味着两件事:一是你无法通过官方安装包获得最新补丁(需自行从源码构建或使用第三方构建);二是任何非安全类缺陷都不会再修。因此长期停留在 security 阶段是有代价的。
EOL 的检测方式
判断一个版本是否 EOL,除了查表,还可以:
- 访问
https://endoflife.date/python获取机器可读的时间线; - 在 CI 中调用 PyPI 或 devguide 的数据做自动检查;
- 监听 Python 官方发布公告(如
python-dev邮件列表、Discourse)。
下面的脚本演示了如何依据内置的 EOL 表,判断当前解释器状态。
# check_lifecycle.py
from __future__ import annotations
import sys
from datetime import date
# 简化的官方时间线:(首次发布, 计划 EOL)
LIFECYCLE: dict[tuple[int, int], tuple[date, date]] = {
(3, 10): (date(2021, 10, 4), date(2026, 10, 1)),
(3, 11): (date(2022, 10, 24), date(2027, 10, 1)),
(3, 12): (date(2023, 10, 2), date(2028, 10, 1)),
(3, 13): (date(2024, 10, 7), date(2029, 10, 1)),
(3, 14): (date(2025, 10, 7), date(2030, 10, 1)),
(3, 15): (date(2026, 10, 1), date(2031, 10, 1)),
}
def describe(version: tuple[int, int], today: date | None = None) -> str:
"""返回指定主次版本的维护状态描述。"""
today = today or date.today()
info = LIFECYCLE.get(version)
if info is None:
return f"未知版本 {version[0]}.{version[1]},请查官方表格"
first_release, eol = info
if today < first_release:
return f"{version[0]}.{version[1]} 尚未发布"
if today > eol:
return f"{version[0]}.{version[1]} 已 EOL({eol.isoformat()}),请尽快升级"
months_left = (eol - today).days // 30
return f"{version[0]}.{version[1]} 仍在支持期,约剩 {months_left} 个月"
if __name__ == "__main__":
current = (sys.version_info.major, sys.version_info.minor)
print(f"当前解释器:{sys.version.split()[0]}")
print(describe(current))这个脚本把时间线写成常量表,便于随官方更新同步;也避免了在代码里硬编码「哪个版本过期」的判断逻辑。
实战示例
示例一:批量评估多个项目的版本风险
假设你维护若干仓库,各自的 .python-version 记录了目标版本,需要一次性评估风险。
# audit_projects.py
from __future__ import annotations
from datetime import date
from pathlib import Path
# 沿用上例的时间线,这里只保留 EOL 日期
EOL: dict[str, date] = {
"3.9": date(2025, 10, 31),
"3.10": date(2026, 10, 1),
"3.11": date(2027, 10, 1),
"3.12": date(2028, 10, 1),
"3.13": date(2029, 10, 1),
"3.14": date(2030, 10, 1),
}
def scan(root: Path) -> list[tuple[str, str, int]]:
"""遍历根目录下的仓库,读取 .python-version 并计算剩余月份。"""
today = date.today()
rows: list[tuple[str, str, int]] = []
for version_file in root.glob("*/.python-version"):
version = version_file.read_text(encoding="utf-8").strip()
# .python-version 可能是 3.13 或 3.13.1,只取主次版本
key = ".".join(version.split(".")[:2])
eol = EOL.get(key)
if eol is None:
rows.append((version_file.parent.name, version, -1))
continue
months = (eol - today).days // 30
rows.append((version_file.parent.name, version, months))
return sorted(rows, key=lambda row: row[2])
if __name__ == "__main__":
for repo, version, months in scan(Path.cwd()):
if months < 0:
tag = "未知"
elif months == 0:
tag = "已过期"
else:
tag = f"剩 {months} 个月"
print(f"{repo:20} Python {version:8} {tag}")运行结果按剩余时间升序排列,最紧急的项目排在最前,便于排优先级。
示例二:在 CI 中阻止使用 EOL 版本
CI 是拦截过期版本的最后一道关口。下面用一段 shell 片段在流水线开头做检查。
# .github/workflows/ci.yml(节选)
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
# 用脚本确认矩阵中的版本都还没 EOL,避免无意中长期跑过期版本
- name: 校验版本生命周期
run: |
python - <<'PY'
import sys
from datetime import date
EOL = {
(3, 11): date(2027, 10, 1),
(3, 12): date(2028, 10, 1),
(3, 13): date(2029, 10, 1),
}
key = (sys.version_info.major, sys.version_info.minor)
eol = EOL.get(key)
if eol is None:
raise SystemExit(f"未知版本 {key},请更新 EOL 表")
if date.today() > eol:
raise SystemExit(f"Python {key[0]}.{key[1]} 已 EOL,请从矩阵中移除")
print(f"Python {key[0]}.{key[1]} 生命周期检查通过")
PY把 EOL 表放进 CI 后,当某个版本到期时流水线会自动失败,提醒维护者更新矩阵,而不是默默继续运行。
示例三:规划一次跨版本的迁移
从 3.10(已 EOL)迁移到 3.13,可以按下面的节奏推进:
# 第一步:盘点现状
python3 --version # 确认当前版本
grep -r "requires-python" --include="pyproject.toml" . # 盘点声明的范围
# 第二步:在开发环境安装新版本并跑测试
pyenv install 3.13.1
pyenv local 3.13.1
python -W error::DeprecationWarning -m pytest -q
# 第三步:同时保留旧版本,做对照测试
pyenv install 3.10.22
PYENV_VERSION=3.10.22 python -m pytest -q
# 第四步:更新声明与镜像
# - pyproject.toml 中 requires-python 改为 ">=3.11"
# - Dockerfile 中 FROM python:3.10-slim 改为 python:3.13.1-slim
# - CI 矩阵去掉 3.10,加入 3.13
# 第五步:部署到预发布,观察一个发布周期后再上生产跨度过大时,可拆成 3.10 → 3.11 → 3.12 → 3.13 的渐进路线,每步都完整验证。
示例四:用 endoflife.date 的 API 做自动提醒
手工维护 EOL 表容易过期。endoflife.date 提供了公开 JSON 接口,可以让脚本自动获取最新数据。
# eol_reminder.py
from __future__ import annotations
import json
import sys
import urllib.request
API = "https://endoflife.date/api/python.json"
def fetch_cycles() -> list[dict[str, object]]:
"""从 endoflife.date 拉取 Python 各版本的生命周期数据。"""
with urllib.request.urlopen(API, timeout=10) as resp: # noqa: S310
return json.load(resp)
def find_cycle(cycles: list[dict[str, object]], cycle: str) -> dict[str, object] | None:
"""按主次版本号(如 3.13)查找对应周期。"""
for item in cycles:
if str(item.get("cycle")) == cycle:
return item
return None
if __name__ == "__main__":
current = f"{sys.version_info.major}.{sys.version_info.minor}"
cycles = fetch_cycles()
info = find_cycle(cycles, current)
if info is None:
print(f"未找到 {current} 的生命周期数据")
elif info.get("eol") is True:
print(f"Python {current} 已 EOL,请尽快升级")
else:
print(f"Python {current} 的 EOL 日期为 {info.get('eol')}")该接口返回的字段包括 cycle(版本线)、releaseDate(首次发布)、eol(EOL 日期,若为 true 表示已结束)、latest(最新补丁版本)等。把它接入定时任务或 CI 的每日检查,就能在版本临近到期时主动提醒。
注意:第三方接口的可用性与字段结构可能变化,脚本应做好异常处理,不要把它的结果作为唯一依据。
注意事项
- EOL 不等于「还能跑」:代码当然还能运行,但已知漏洞不会被修复,公网服务尤其危险。
- security 阶段无安装包:官方只发源码版,依赖官方二进制安装包的场景需要另想办法。
- 日期可能微调:发布计划中的日期是「计划值」,官方保留调整权利,重要决策前请查阅最新表格。
- 操作系统自带版本不等于可用版本:macOS 自带的
python3常被系统脚本依赖,不应作为项目解释器。 - 不要依据
sys.version_info的补丁号做逻辑:补丁号随环境变化,业务代码不应依赖它。 - EOL 版本遇到 CVE 无官方补丁:只能靠升级、隔离或自行打补丁缓解。
- 引用时间线需注明来源:文档或脚本中的 EOL 表应标注更新日期,避免长期未维护后误导他人。
常见问题
Q:为什么 3.13 的完整支持期比 3.12 长? 因为 PEP 602 在 2024 年被修订,把新版本的完整支持期从 1.5 年延长至 2 年。该修订自 3.13 起生效,3.9~3.12 仍按旧规则。
Q:EOL 后还能从哪获取补丁? 官方渠道不再提供。部分 Linux 发行版会为其仓库中的 Python 回移安全补丁(如 Debian、Red Hat),但这是发行版行为,不代表官方支持。
Q:如何第一时间得知新版本发布? 关注 python.org 的下载页与发布公告、python-dev 邮件列表、Python Discourse 的 Core Development 板块,或使用 endoflife.date 的 API 做自动化通知。
Q:预发布版本能用于生产吗? 不能。alpha/beta/rc 都可能包含未修复的严重问题,仅适合用于兼容性测试。
最佳实践
- 生产环境只选择处于 bugfix 阶段的版本,兼顾稳定性与支持时长。
- 在 CI 中内置 EOL 检查,让过期版本自动使流水线失败。
- 至少提前 6 个月规划临近 EOL 的版本迁移,避免被动救火。
- 订阅官方发布渠道,及时获取版本状态变更信息。
- 把 EOL 时间线与
requires-python一起维护在项目文档中,形成可追溯的决策依据。 - 使用版本管理器隔离系统 Python,绝不直接升级操作系统自带解释器。
- 升级路线优先选择渐进式,每跨一个特性版本都完整验证。
下一节
下一章将进入交互式编程:REPL 基础操作