news 2026/7/10 19:14:15

从零到一 —— 使用 PyO3 将 Rust 函数编译为 Python 模块

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从零到一 —— 使用 PyO3 将 Rust 函数编译为 Python 模块

1. 引言:消除隔阂,一步调用

在上一篇中,我们分别用 Python 和 Rust 写了两个独立的 HTTP 服务器。虽然对比了性能,但它们本质上是两个独立的程序。

在实际开发中,我们往往不想维护两套服务。我们希望的结果是:Python 负责主流程和业务逻辑,而在性能瓶颈处,直接调用 Rust 编写的函数,就像调用普通的 Python 库一样自然。

这就需要一个桥梁。PyO3​ 就是这个桥梁,它允许你将 Rust 代码编译成一个.so(Linux/Mac)或.pyd(Windows)的二进制模块。Python 通过import加载它,中间的转换开销极小。

今天,我们就把上一篇中的count_words函数,打包成一个名为rust_analyzer的 Python 扩展库。

2. 环境准备:Maturin 工具链

为了编译 Rust 生成的 Python 模块,我们需要特定的工具。maturin是 PyO3 官方推荐的工具,它极大地简化了配置过程。

2.1 创建虚拟环境

为了保持环境整洁,我们先创建一个 Python 虚拟环境:

# 创建项目文件夹 mkdir pyo3_demo && cd pyo3_demo # 创建虚拟环境 python -m venv venv source venv/bin/activate # Windows: venv\Scripts\activate

2.2 安装 Maturin

pip install maturin

3. 初始化 PyO3 项目

maturin提供了一个命令,可以快速生成符合 PyO3 规范的项目骨架。

# 在当前目录下初始化一个名为 rust_analyzer 的库 maturin init --bindings pyo3

运行后,它会询问你选择哪种绑定方式,直接回车选择默认的pyo3即可。

生成的项目结构如下:

pyo3_demo/ ├── Cargo.toml # Rust 项目管理文件 ├── pyproject.toml # Python 构建配置文件 └── src/ └── lib.rs # Rust 源代码(主要编辑这里)

4. 编写 Rust 代码:导出函数

打开src/lib.rs,清空默认内容,填入以下代码。这段代码的核心任务是:告诉 Rust 如何将函数暴露给 Python

文件路径:src/lib.rs

/* * 使用 PyO3 编写 Python 扩展模块 * 目标:将上一篇的 Rust 词频统计逻辑暴露给 Python */ // 引入 PyO3 预导入模块,包含所有必要的宏和类型 use pyo3::prelude::*; use std::collections::HashMap; /// 核心逻辑:纯粹的 Rust 函数 /// 这个函数不关心 Python,只负责高效的词频计算 /// 输入: 文本字符串和需要返回的 Top N /// 输出: 元组数组 (单词, 次数) fn count_words_rust(text: &str, top_n: usize) -> Vec<(String, u64)> { let mut freq_map = HashMap::new(); // 使用 Rust 高效的迭代器进行分词和统计 text.split(|c: char| !c.is_alphanumeric()) .filter(|s| !s.is_empty()) .for_each(|word| { *freq_map.entry(word.to_lowercase()).or_insert(0) += 1; }); // 排序并截取前 N 名 let mut freq_vec: Vec<_> = freq_map.into_iter().collect(); freq_vec.sort_by(|a, b| b.1.cmp(&a.1)); freq_vec.truncate(top_n); freq_vec } /// Python 接口函数 /// #[pyfunction] 宏:标记此函数为 Python 可调用函数 /// 参数类型会自动转换:Python str -> &str, Python int -> usize /// 返回值会自动转换:Vec<(String, u64)> -> Python list of tuples #[pyfunction] fn count_words(text: &str, top_n: usize) -> PyResult<Vec<(String, u64)>> { // 调用 Rust 核心逻辑 let result = count_words_rust(text, top_n); // Ok(...) 是 PyO3 的标准返回方式,用于处理 Python 异常 Ok(result) } /// 定义 Python 模块 /// #[pymodule] 宏:定义模块名称为 rust_analyzer /// _py: Python 解释器的句柄(GIL Token) /// m: 模块对象本身 #[pymodule] fn rust_analyzer(_py: Python<'_>, m: &PyModule) -> PyResult<()> { // 将 count_words 函数注册到模块中 m.add_function(wrap_pyfunction!(count_words, m)?)?; Ok(()) }

关键点解析(博客重点):

  1. 分离逻辑count_words_rust是纯逻辑,count_words是接口层。这样做的好处是 Rust 代码可以不依赖 Python 环境进行单元测试。

  2. #[pyfunction]:这是魔法发生的地方,它让 Rust 函数能被import进来。

  3. PyResult:Rust 的错误处理与 Python 的异常系统对接。

5. 编译与安装(开发模式)

这是最关键的一步。我们需要将 Rust 代码编译成二进制文件,并链接到当前的 Python 虚拟环境中。

在项目根目录(pyo3_demo/)下执行:

maturin develop

发生了什么?

  1. cargo开始编译 Rust 代码。

  2. 生成一个二进制文件(如rust_analyzer.cpython-310-x86_64-linux-gnu.so)。

  3. maturin将这个文件复制到当前虚拟环境的site-packages目录下。

看到类似📦 Built wheel for CPython 3.10✏️ Installed rust_analyzer的字样,就意味着成功了!

6. 在 Python 中调用

现在,激动人心的时刻到了。我们可以在 Python 中像使用普通库一样使用刚才编译的 Rust 模块。

在项目根目录下创建一个测试文件test.py

文件路径:test.py

# 直接导入我们刚刚用 Rust 编译的模块 import rust_analyzer def test_rust_function(): print("--- Testing Rust Module ---") # 准备测试数据 text = "Rust is fast and safe. Python is flexible and easy. Rust and Python together are powerful." top_n = 3 # 直接调用 Rust 函数 # PyO3 自动帮我们把 Python str 转成了 Rust &str # 并把 Rust 返回的 Vec<(String, u64)> 转成了 Python list result = rust_analyzer.count_words(text, top_n) print(f"Input Text: {text}") print(f"Top {top_n} words:") for word, count in result: print(f" {word}: {count}") if __name__ == "__main__": test_rust_function()

运行测试:

python test.py

预期输出:

--- Testing Rust Module --- Input Text: Rust is fast and safe. Python is flexible and easy. Rust and Python together are powerful. Top 3 words: rust: 2 python: 2 and: 2

7. 流程总结与 Mermaid 图示

整个流程可以简化为以下几个步骤:

8. 总结

至此,我们成功打通了 Rust 到 Python 的调用链路。

  • 没有 HTTP 开销:函数调用发生在进程内部,速度极快。

  • 开发体验流畅maturin develop支持增量编译,修改 Rust 代码后重新运行该命令即可更新模块。

  • 类型安全:Rust 的强类型系统在编译期拦截了大量错误,Python 端拿到的数据是安全的。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/10 19:13:48

高效实战:全面解析VMPDump的VMProtect 3.X x64保护破解技巧

高效实战&#xff1a;全面解析VMPDump的VMProtect 3.X x64保护破解技巧 【免费下载链接】vmpdump A dynamic VMP dumper and import fixer, powered by VTIL. 项目地址: https://gitcode.com/gh_mirrors/vm/vmpdump 面对VMProtect 3.X x64保护的软件&#xff0c;你是否曾…

作者头像 李华
网站建设 2026/7/10 19:13:30

STM32与AD7175-8高精度数据采集系统设计指南

1. 项目背景与核心器件选型在工业测量、医疗设备和精密仪器领域&#xff0c;高精度信号采集一直是工程师面临的挑战。AD7175-8作为ADI公司推出的24位Σ-Δ型ADC&#xff0c;以其250kSPS采样率和8通道差分输入能力&#xff0c;成为精密信号采集的理想选择。搭配STM32F413RH这款C…

作者头像 李华
网站建设 2026/7/10 19:11:47

Edyn物理引擎调试与优化:常见问题解决方案与性能调优

Edyn物理引擎调试与优化&#xff1a;常见问题解决方案与性能调优 【免费下载链接】edyn Edyn is a real-time physics engine organized as an ECS. 项目地址: https://gitcode.com/gh_mirrors/ed/edyn Edyn是一个基于ECS架构的实时物理引擎&#xff0c;为游戏开发提供高…

作者头像 李华
网站建设 2026/7/10 19:07:50

终极网页浏览效率神器:右键滚动条一键返回顶部

终极网页浏览效率神器&#xff1a;右键滚动条一键返回顶部 【免费下载链接】UserScript &#x1f435; 自用的一些乱七八糟 油猴脚本~ 项目地址: https://gitcode.com/gh_mirrors/us/UserScript 你是否曾经在浏览超长网页时感到困扰&#xff1f;当你在阅读一篇精彩的技…

作者头像 李华