2024 年 10 月发布的 Python 3.13,是 CPython 历史上最"激进"的版本:可选的无 GIL 构建(自由线程,free-threaded)与实验性 JIT 编译器在同一版落地。虽然两者默认都不开启、也都标注为实验性,但它们标志着 Python 在"多核并行"与"运行速度"两条路上迈出了方向性的一步。本文讲清这两个新东西是什么、怎么用,以及 3.13 还有哪些值得注意的变化。
1. 自由线程:没有 GIL 的 Python
GIL(全局解释器锁)让同一进程内的多个线程无法真正并行执行 CPU 密集代码,这是 Python 被诟病多年的"老大难"。3.13 提供了不带 GIL 的自由线程构建,每个线程可以真正跑在独立 CPU 核心上。先确认你用的是哪种构建:
import sys
# 标准构建输出 True;自由线程构建输出 False
print(sys._is_gil_enabled())
在自由线程构建下,多线程计算可以真正并行。用四个线程各自做大量纯计算,对比带 GIL 与不带 GIL 的运行时间,差异会非常直观:
import threading
results = []
def work(n):
total = sum(i * i for i in range(n))
results.append(total)
threads = [threading.Thread(target=work, args=(5_000_000,)) for _ in range(4)]
for t in threads:
t.start()
for t in threads:
t.join()
print(sum(results))
需要强调:自由线程目前是实验特性,需要专门的构建(如 pyenv 的 3.13.x t 变体);部分依赖 C 扩展的库(numpy、pandas 等)需要适配并自行加锁,才能保证多线程下的安全。
为什么自由线程这么受关注?现代服务器动辄几十个核心,而带 GIL 的 Python 无法用多线程吃满 CPU。自由线程让"线程 + 锁"重新成为并行编程的可行选择,而不必被迫使用多进程(multiprocessing)或异步。代价是线程安全要开发者自己负责——共享可变对象必须加锁,这恰恰是很多 Python 程序员不太熟悉的领域。
怎么决定用线程还是进程?经验法则:任务以计算为主、数据量小,用自由线程的线程池;任务需要共享大块内存或复杂状态,多进程 + 队列仍是更稳妥的选择。自由线程的意义在于"多了一个选项",而不是取代多进程。
生态现状如何?到 2026 年,主流科学计算库(如 numpy、pandas)都已发布支持自由线程构建的版本,但部分小众 C 扩展仍未适配;切换前最好用项目的测试套件在自由线程构建上完整跑一遍,再决定是否落地。
| 对比项 | 标准构建(带 GIL) | 自由线程构建 |
|---|---|---|
| 是否含 GIL | 是 | 否(实验性) |
| 默认 / 可选 | 默认 | 需专门构建 |
| 第三方库兼容性 | 与既有生态完全兼容 | 部分 C 扩展需适配 |
| CPU 密集多线程 | 无法真正并行 | 可并行 |
| 适用场景 | 生产环境首选 | 实验与评估 |
2. 实验性 JIT 编译器
3.13 还内置了实验性的"二级 JIT":解释器在运行时把热点代码编译成机器码,进一步提速。是否启用可以用 sys.flags.jit 检查:
import sys
print(sys.flags.jit) # 1 表示 JIT 已启用(需要专门构建)
def heavy(n):
total = 0
for i in range(n):
total += i
return total
print(heavy(10_000_000))
JIT 默认关闭,且需要从源码编译并开启 --enable-experimental-jit 才会生效。对普通用户来说,它更像"未来预览"——真正的成熟版本要等 3.14 及以后。
原理上,JIT 是在解释执行之外增加一条"优化流水线":解释器先统计哪些函数被高频调用,再把它们的字节码编译成本地机器码,后续直接执行机器码。由于目前仍是实验性实现,收益视工作负载而定,官方也明确表示完整的 JIT 优化要等后续版本逐步完善。
3. 新 REPL 与类型系统的小步快跑
3.13 的交互式解释器全面重写:支持多行编辑、语法高亮、自动缩进、历史搜索,还提供 F1/F2/F3 快捷帮助,体验接近 IPython 的基础功能。类型系统方面,PEP 742 的 TypeIs 让"类型守卫"更精确——类型检查器能根据守卫函数把变量收窄到具体类型:
from typing import TypeIs
def is_str_list(value: object) -> TypeIs[list[str]]:
return isinstance(value, list) and all(
isinstance(x, str) for x in value
)
def handle(data: object):
if is_str_list(data):
print(len(data), data[0].upper()) # 此处 data 已被收窄为 list[str]
else:
print("不是字符串列表")
新 REPL 值得上手一试:直接粘贴多行代码会自动保持缩进,按 F2 浏览历史命令,F3 查看帮助;在终端里写临时脚本、调试表达式都比以前顺手得多。
此外,一批年久失修的模块(cgi、telnetlib、audioop 等)在 3.13 被正式移除,升级前建议全局搜索代码里是否还在引用它们;标准库同时新增了 copy.replace、dbm.sqlite3 等实用小工具。
4. 其它 3.13 更新速览
- PEP 696:类型参数支持默认值,泛型缺省场景更省事
- copy.replace:不改原对象、返回修改后副本的新工具
- dbm.sqlite3:dbm 接口新增 SQLite 后端,读写更稳定
- 模块清理:cgi、telnetlib、audioop 等老模块被移除,升级前记得全局排查
- 随机数安全:random 模块默认改用更安全的种子来源
5. 如何安装 Python 3.13
# 标准构建(默认,带 GIL)
pyenv install 3.13.1
pyenv local 3.13.1
python3.13 -m pip install --upgrade pip
python3.13 -m venv .venv && source .venv/bin/activate
# 自由线程构建(macOS / Linux)
pyenv install 3.13.1t
# 实验性 JIT 需要从源码编译
# ./configure --enable-experimental-jit
# make -j$(nproc)
6. 值不值得升级?
分人群回答。如果你是普通应用开发者:3.13 的标准构建完全可以升级——它兼容性良好、REPL 体验大幅提升、性能与 3.12 相当或略好;但不必为了自由线程和 JIT 特意折腾,这两个特性默认关闭且实验性较强,生产中暂时用不上。如果你在做 CPU 密集的并行计算,或想提前评估"无 GIL 生态":可以装一个自由线程构建的虚拟环境做实验,但生产部署建议等特性在 3.14 稳定后再考虑。一句话:3.13 是"面向未来的版本",现在就升,稳赚不亏;激进玩法,再等等。
落地前做一个小检查:用 pip install --only-binary :all: 包名 或查看项目文档,确认关键依赖是否提供 3.13 的 wheel;如果某个核心库还不支持,把它钉在旧版本环境里,新代码跑 3.13,过渡期完全可以共存。
💡 学习建议:先装标准构建,在终端里敲几行代码体验新 REPL 的多行编辑;再用 pyenv 装一个 3.13.1t,运行上面那个线程池计算程序,对比带 GIL 与无 GIL 构建的耗时——亲眼看到差异,比背任何结论都管用。