Skip to content

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 意味着连安全漏洞都不再修复,继续使用会把已知漏洞长期暴露在生产环境。

语法与用法 ​

查看本机版本与状态是最基本的操作。

bash
# 查看解释器版本
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

在代码里判断版本,用于条件分支:

python
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)

通过版本管理器查看与切换:

bash
# 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.15prerelease2026-10(计划)2031-10PEP 790
3.14bugfix2025-10-072030-10PEP 745
3.13bugfix2024-10-072029-10PEP 719
3.12security2023-10-022028-10PEP 693
3.11security2022-10-242027-10PEP 664
3.10end-of-life2021-10-042026-10-01PEP 619
3.9end-of-life2020-10-052025-10-31PEP 596
3.8end-of-life2019-10-142024-10-07PEP 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 的命名约定,安装器默认不会选中它们:

后缀含义示例
aNalpha,第 N 个 alpha3.15.0a1
bNbeta,第 N 个 beta,特性冻结3.15.0b1
rcNrelease 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 表,判断当前解释器状态。

python
# 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 记录了目标版本,需要一次性评估风险。

python
# 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 片段在流水线开头做检查。

bash
# .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,可以按下面的节奏推进:

bash
# 第一步:盘点现状
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 接口,可以让脚本自动获取最新数据。

python
# 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 都可能包含未修复的严重问题,仅适合用于兼容性测试。

最佳实践 ​

  1. 生产环境只选择处于 bugfix 阶段的版本,兼顾稳定性与支持时长。
  2. 在 CI 中内置 EOL 检查,让过期版本自动使流水线失败。
  3. 至少提前 6 个月规划临近 EOL 的版本迁移,避免被动救火。
  4. 订阅官方发布渠道,及时获取版本状态变更信息。
  5. 把 EOL 时间线与 requires-python 一起维护在项目文档中,形成可追溯的决策依据。
  6. 使用版本管理器隔离系统 Python,绝不直接升级操作系统自带解释器。
  7. 升级路线优先选择渐进式,每跨一个特性版本都完整验证。

下一节

下一章将进入交互式编程:REPL 基础操作

参考链接 ​