在 Python Language Summit 2026 上,David Hewitt 分享了 Rust for CPython 项目的最新状态、首个模块,以及未来可能采用的验收标准。真正值得关注的,不只是“CPython 能不能用 Rust”,而是一个更现实的问题:Rust 代码如何进入一个拥有数十年历史、覆盖大量平台、对兼容性极其敏感的解释器核心。
现有摘要没有给出首个模块的名称或验收标准全文,因此不宜猜测具体实现。不过,我们可以从 CPython 的工程约束出发,理解这项工作的难点,并用一个最小扩展模块亲手验证 Python 与 Rust 交界处会遇到什么。
这不是简单地把 C 改写成 Rust
在普通应用项目里,把一段 C 代码迁移到 Rust,通常可以围绕内存安全、并发安全和类型系统展开。但 CPython 的情况更复杂。
CPython 本身既是解释器,也是庞大扩展生态依赖的平台。一个进入核心仓库的 Rust 模块至少会触及以下问题:
- 对象生命周期:Rust 的借用规则必须正确映射到 Python 对象的引用计数和垃圾回收机制。
- 异常传播:Rust 的
Result、panic 与 Python 异常之间需要明确边界,不能让 panic 穿过 FFI。 - GIL 与并发:Rust 的线程安全类型并不自动意味着 Python C API 的调用是安全的。
- 构建链变化:引入 Rust 编译器会影响源码构建、交叉编译、发行包制作和平台支持。
- 调试与可维护性:核心开发者需要能够审查、定位和修复同时跨越 Python、C 与 Rust 的问题。
- ABI 与兼容性:内部实现可以变化,但不能轻易破坏扩展模块、嵌入式应用或受支持平台。
因此,“首个模块”更像一块试金石。它需要证明 Rust 不仅能写出正确代码,也能进入 CPython 的构建、测试、发布和维护流程。
验收标准应该回答哪些问题
来源提到项目正在考虑潜在的 acceptance criteria,但摘要没有列出具体条款。若把它转化为可执行的工程检查表,可以重点观察下面这些维度;这是基于 CPython 集成场景的实践性归纳,并非对会上标准的逐条转述。
| 维度 | 应回答的问题 |
|---|---|
| 正确性 | 行为是否与现有实现一致?异常类型、边界输入和引用计数是否正确? |
| 安全边界 | unsafe 和 FFI 是否足够集中、可审计?Rust panic 是否被限制在边界内? |
| 性能 | 启动时间、运行速度、内存占用和二进制大小是否出现回退? |
| 可移植性 | CPython 支持的平台中,哪些已有可靠 Rust 工具链?缺失工具链时如何构建? |
| 可维护性 | 核心维护者能否在没有原作者参与时继续修改和排错? |
| 发布流程 | 源码包、官方安装包、调试符号、交叉编译和重现构建如何处理? |
| 兼容性 | 是否改变公开 C API、稳定 ABI、嵌入接口或扩展模块行为? |
性能尤其不应只测“热循环快了多少”。对于解释器组件,更完整的基准还应覆盖:
冷启动时间
导入模块耗时
典型工作负载吞吐量
峰值与常驻内存
生成物体积
调试构建与发布构建的差异
多平台测试结果
如果 Rust 实现只在单个微基准中领先,却明显增加构建成本或平台维护负担,它未必适合进入 CPython 核心。
动手验证 Python 与 Rust 的边界
下面可以这样实践:用 PyO3 构建一个最小 Python 扩展,观察类型转换、异常映射和动态库构建过程。这不是 Rust for CPython 项目的接口,也不代表其首个模块实现方式;它只是一个可复制的边界实验。
准备 Python、Rust 和 Cargo 后,在 macOS 或 Linux 的 Bash 中执行:
mkdir rust-cpython-lab
cd rust-cpython-lab
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip maturin
cargo init --lib --name fastsum
cargo add pyo3 --features extension-module
cat >> Cargo.toml <<'EOF'
[lib]
name = "fastsum"
crate-type = ["cdylib"]
EOF
cat > pyproject.toml <<'EOF'
[build-system]
requires = ["maturin>=1,<2"]
build-backend = "maturin"
[project]
name = "fastsum"
version = "0.1.0"
requires-python = ">=3.9"
[tool.maturin]
module-name = "fastsum"
EOF
cat > src/lib.rs <<'EOF'
use pyo3::{exceptions::PyOverflowError, prelude::*};
#[pyfunction]
fn sum_i64(values: Vec<i64>) -> PyResult<i64> {
values.into_iter().try_fold(0_i64, |acc, item| {
acc.checked_add(item)
.ok_or_else(|| PyOverflowError::new_err("64-bit integer overflow"))
})
}
#[pymodule]
fn fastsum(module: &Bound<'_, PyModule>) -> PyResult<()> {
module.add_function(wrap_pyfunction!(sum_i64, module)?)?;
Ok(())
}
EOF
maturin develop --release
python - <<'PY'
import fastsum
assert fastsum.sum_i64([1, 2, 3, 4]) == 10
print(fastsum.sum_i64(range(100)))
try:
fastsum.sum_i64([2**63 - 1, 1])
except OverflowError as exc:
print(type(exc).__name__, exc)
PY
运行前需要确认本机的 python3、cargo 和 Rust 工具链可用。Windows 用户需要替换虚拟环境激活命令。
这个例子刻意没有直接使用 sum(),而是通过 checked_add 检测整数溢出,再把错误转换成 Python 的 OverflowError。它体现了集成时的一项基本原则:
Rust 的安全模型不会自动覆盖语言边界;边界上的类型、所有权、错误和 panic 都必须显式设计。
真实的 CPython 核心模块还会面对更底层的问题,例如借用的 Python 对象是否会被错误保存、引用计数是否平衡、释放 GIL 后还能调用哪些 API,以及解释器关闭阶段资源如何销毁。
不要把“用了 Rust”当作验收结果
Rust 可以减少空指针、释放后使用和部分数据竞争风险,但它不会自动解决所有问题:
unsafe代码仍可能破坏内存安全。- FFI 声明写错后,编译器无法理解另一侧的真实约束。
- 逻辑错误、资源泄漏和死锁不会因为使用 Rust 而消失。
- panic 如果跨越不允许展开的 FFI 边界,可能导致进程终止或未定义行为。
- 新工具链可能让某些小众平台、交叉编译环境或下游发行版承担额外成本。
更合理的评价方式是比较迁移前后的整体风险:Rust 是否缩小了需要人工审计的区域?unsafe 是否被压缩到少数边界模块?测试是否覆盖异常路径和生命周期?维护者是否能理解并持续修改它?
采用时看证据,不看语言标签
Rust for CPython 的意义,在于探索解释器核心能否获得更强的内存安全保障,同时不牺牲 CPython 长期坚持的兼容性、可移植性和可维护性。首个模块只是开始,真正决定项目能否被接受的是一套可重复验证的证据。
关注后续进展时,可以使用这份简短清单:
- 行为兼容测试是否完整;
- FFI 与
unsafe是否集中且有文档; - panic、Python 异常和资源清理是否有明确策略;
- 性能数据是否覆盖真实工作负载;
- 支持平台和工具链要求是否清楚;
- 构建失败时是否有可诊断的信息;
- 是否已有足够多的维护者能够审查和接手代码。
对于 CPython 这样的基础设施项目,最有说服力的结论从来不是“Rust 更安全”,而是“这一部分代码在明确边界、完整测试和可持续维护的条件下,确实变得更安全了”。