Skip to content

Python 3.12 路线图

目标定义

这里的“切换为更现代的 Python 3.12”在 BigWorld 语境下,至少包含四件事:

  1. 内嵌解释器从 Python 2.7 迁移到 Python 3.12
  2. C/C++ 与 Python 的桥接层完成 Python 3 API 适配
  3. 项目自带共享模块与第三方 Python 包完成替换或重建
  4. 构建、打包、部署和运行时资源布局完成同步调整

如果只完成第 1 项,不算迁移成功。

先给结论

不建议直接在当前主线一次性切到 Python 3.12。推荐采用“四阶段迁移策略”。

阶段 0:建立可信基线

目标是回答一个问题:当前仓库到底能否稳定构建和运行。

必做事项

  • 校验 Linux 服务端在当前文档假设下能否完整构建。
  • 校验关键服务进程最小启动链路。
  • 校验客户端/工具链是否具备最小可编译性。
  • 补齐缺失脚本和漂移路径,例如 control_cluster.py 的真实来源。
  • 固化一份“现状构建手册”和“现状依赖清单”。

输出物

  • 可复现的构建步骤
  • 可执行的 smoke test
  • 当前 Python 耦合点清单

没有这一步,后续迁移不可控。

阶段 1:先升级到 Python 3 兼容抽象层

目标不是直接接入 3.12,而是先把代码从 Python 2 专有 API 中抽离出来。

核心动作

  • lib/pyscriptlib/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 的构建逻辑
  • 重新确认以下目录约定:
    • Lib
    • lib-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, e
  • iteritems
  • xrange
  • unicode/str/bytes
  • cPickle

第三方包

当前打包的旧依赖不能直接带入 Python 3.12,应按“替换优先”处理:

  • oursql 优先考虑替换为现代 MySQL 驱动,而不是继续修补。
  • SQLAlchemy 0.6.6 若必须保留,需评估 API 改造成本;更现实的是隔离旧调用并升级到现代版本。
  • Pymplerpika 视实际使用面决定升级或移除。

原则

  • 先证明“哪些依赖仍被真实使用”
  • 再决定“升级、替换还是删除”

这符合 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
  • 在服务端先切而忽略编辑器和客户端

这些做法短期看快,长期一定返工。

推荐的近期行动

如果下一步要真正启动迁移,建议先做三件事:

  1. 建一个 python-modernization 分支外的分析清单,但不要立即改业务逻辑。
  2. lib/pyscriptlib/script 做一次专门的接口普查,形成 Python 2 专有 API 清单。
  3. 在当前仓库内补一套最小构建与启动验证脚本,先让现状可测。

最终判断

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 (性能优化)

参考资料

按源码证据链、源码取舍和验证边界组织,而不是按目录机械罗列。