Python 3.12 路线图
目标定义
这里的“切换为更现代的 Python 3.12”在 BigWorld 语境下,至少包含四件事:
- 内嵌解释器从 Python 2.7 迁移到 Python 3.12
- C/C++ 与 Python 的桥接层完成 Python 3 API 适配
- 项目自带共享模块与第三方 Python 包完成替换或重建
- 构建、打包、部署和运行时资源布局完成同步调整
如果只完成第 1 项,不算迁移成功。
先给结论
不建议直接在当前主线一次性切到 Python 3.12。推荐采用“四阶段迁移策略”。
阶段 0:建立可信基线
目标是回答一个问题:当前仓库到底能否稳定构建和运行。
必做事项
- 校验 Linux 服务端在当前文档假设下能否完整构建。
- 校验关键服务进程最小启动链路。
- 校验客户端/工具链是否具备最小可编译性。
- 补齐缺失脚本和漂移路径,例如
control_cluster.py的真实来源。 - 固化一份“现状构建手册”和“现状依赖清单”。
输出物
- 可复现的构建步骤
- 可执行的 smoke test
- 当前 Python 耦合点清单
没有这一步,后续迁移不可控。
阶段 1:先升级到 Python 3 兼容抽象层
目标不是直接接入 3.12,而是先把代码从 Python 2 专有 API 中抽离出来。
核心动作
- 在
lib/pyscript、lib/script建立统一兼容包装层。 - 把散落的
PyString_*、PyInt_*、Py_InitModule收口到局部适配接口。 - 统一处理:
- 字符串
- bytes
- 整数
- 模块初始化
- 异常格式化
pickle/cPickle行为
原则
KISS先做 API 收口,不要一开始重写所有脚本系统。DRY不要在每个子模块里独立写一份 Python 2/3 判断分支。YAGNI只抽象当前真实使用的 API,不预建“大而全”的绑定框架。
预期结果
- 业务层不再直接依赖大面积 Python 2 专有符号
- 为后续切换解释器版本创造局部替换条件
阶段 2:迁移嵌入式运行时与标准库布局
核心动作
- 替换
third_party/python的来源策略 - 重新设计
third_party_python.mak的构建逻辑 - 重新确认以下目录约定:
Liblib-dynload-*site-packages
- 调整动态模块打包方式
重点阻塞
- Python 3.12 的构建方式与 Python 2.7 显著不同
- 旧版 OpenSSL/系统依赖可能不再适配
- 旧式
configure + make定制补丁要重新评估
建议
在这一阶段同步评估平台升级,优先考虑:
- 新版 Rocky / Alma / Ubuntu LTS 构建环境
- 更新 CMake 基线
- 更新编译器基线
如果继续锁死在 CentOS 7,迁移成本会被显著放大。
阶段 3:迁移 Python 业务脚本和第三方包
Python 脚本本身
首方 .py 文件数量不算大,理论上是迁移成本较低的一层,但仍需检查:
print语法except Exception, eiteritemsxrangeunicode/str/bytescPickle
第三方包
当前打包的旧依赖不能直接带入 Python 3.12,应按“替换优先”处理:
oursql优先考虑替换为现代 MySQL 驱动,而不是继续修补。SQLAlchemy 0.6.6若必须保留,需评估 API 改造成本;更现实的是隔离旧调用并升级到现代版本。Pympler、pika视实际使用面决定升级或移除。
原则
- 先证明“哪些依赖仍被真实使用”
- 再决定“升级、替换还是删除”
这符合 YAGNI,避免为死代码支付迁移成本。
阶段 4:端到端验证与双轨切换
验证范围
- 服务端进程启动
- 实体脚本加载
- 数据库交互
- 日志与消息系统
- 编辑器脚本功能
- 客户端脚本调用
建议策略
- 保留 Python 2.7 基线分支
- 新建 Python 3.12 迁移分支
- 建立最小回归清单
- 采用双轨验证,而不是原地覆盖
迁移优先级建议
P0
- 建立 Python C API 兼容层
- 梳理
lib/pyscript/lib/script - 明确缺失脚本与失效构建路径
P1
- 重新设计嵌入式 Python 构建链
- 替换过期第三方 Python 包
- 补齐自动化 smoke test
P2
- 平台基线升级
- 工具链升级
- 清理历史兼容残留
不建议的做法
- 直接全局替换
PyString_->PyUnicode_ - 不做基线验证就引入 Python 3.12
- 继续把所有旧第三方包强行 patch 到 3.12
- 在服务端先切而忽略编辑器和客户端
这些做法短期看快,长期一定返工。
推荐的近期行动
如果下一步要真正启动迁移,建议先做三件事:
- 建一个
python-modernization分支外的分析清单,但不要立即改业务逻辑。 - 对
lib/pyscript和lib/script做一次专门的接口普查,形成 Python 2 专有 API 清单。 - 在当前仓库内补一套最小构建与启动验证脚本,先让现状可测。
最终判断
BigWorld 切换到 Python 3.12 是可做的,但它本质上是一次”嵌入式脚本运行时现代化工程”,不是简单版本升级。
如果按正确顺序推进:
- 先基线
- 再抽象
- 再替换运行时
- 最后迁移脚本与依赖
这件事是可控的。
如果跳过前两步直接升级解释器,失败概率很高。
重要更新:Python 3.13 free-threaded 模式 (no-GIL)
概述
Python 3.13 (2024 年 10 月发布) 引入了 free-threaded 模式 (PEP 703),也称为 no-GIL。这是一个实验性特性,可以彻底改变 BigWorld 的线程模型。
关键特性
| 特性 | 说明 |
|---|---|
| 编译选项 | --disable-gil 或使用 python3.13t |
| 状态 | 实验性,非默认启用 |
| 性能开销 | 单线程 ~5-10% |
| C 扩展兼容性 | 需要重新编译和测试 |
| 内存管理 | 线程安全的引用计数 |
| 内部数据结构 | 线程安全 |
对 BigWorld 的影响
线程模型变革
当前 BigWorld 的线程模型:
主线程 (Reactor + 所有脚本逻辑)
├── 后台线程 1 (数据库)
├── 后台线程 2 (文件 I/O)
└── 后台线程 3 (定时任务)Python 3.13 no-GIL 后的可能模型:
主线程 (Reactor + 网络)
├── 脚本线程池 (并行执行实体逻辑)
├── 后台线程 1 (数据库)
├── 后台线程 2 (文件 I/O)
└── 后台线程 3 (定时任务)性能提升潜力
- BaseApp:可并行处理多个玩家的脚本逻辑
- CellApp:可并行处理不同 Cell 的实体更新
- 吞吐量:理论上可提升 N 倍 (N = CPU 核心数)
迁移路径建议
阶段 1:验证兼容性 (当前)
bash
# 1. 测试 Python 3.13 标准构建
python3.13 --version
# 2. 测试 free-threaded 构建
python3.13t --version
# 3. 运行现有测试
python3.13t -m pytest tests/阶段 2:C 扩展适配
cpp
// 检查 C 扩展兼容性
// Python 3.13 free-threaded 需要:
// 1. 使用新的引用计数 API
// 2. 避免全局状态
// 3. 使用线程安全的数据结构阶段 3:逐步启用并行
cpp
// 1. 先在非关键路径测试
// 2. 逐步启用并行脚本执行
// 3. 监控性能和稳定性风险与缓解
| 风险 | 缓解措施 |
|---|---|
| C 扩展不兼容 | 逐步测试,优先级排序 |
| 单线程性能下降 | Profile 驱动优化 |
| 调试复杂度增加 | 保留单线程模式作为回退 |
| 第三方库支持不全 | 选择性启用,关键路径保守 |
建议策略
当前状态: Python 2.7 + GIL
↓
阶段 1: Python 3.12 + GIL (稳定优先)
↓
阶段 2: Python 3.13 + GIL (验证兼容性)
↓
阶段 3: Python 3.13t + no-GIL (非关键路径测试)
↓
阶段 4: 全面启用 no-GIL (性能优化)