Python与Rust混合编程实战:发挥两种语言的优势

张开发
2026/4/8 17:11:45 15 分钟阅读

分享文章

Python与Rust混合编程实战:发挥两种语言的优势
Python与Rust混合编程实战发挥两种语言的优势后端转 Rust 的萌新ID 第一程序员——名字大人很菜暂时。正在跟所有权和生命周期死磕日常记录 Rust 学习路上的踩坑经验和啊哈时刻代码片段保证能跑。保持学习保持输出。欢迎大佬们轻喷也欢迎同好一起进步。前言最近在学习 Rust 的过程中我一直在思考如何将 Rust 与 Python 结合起来发挥两种语言的优势。Python 以其简洁易学、生态丰富而闻名而 Rust 则以其内存安全、高性能而受到青睐。如果能够将两者结合起来岂不是能创造出既开发效率高又运行性能好的应用今天就来分享一下我的 Python 与 Rust 混合编程实践希望能帮到和我一样的萌新们。为什么要混合使用 Python 和 RustPython 的优势开发效率高Python 语法简洁代码量少开发速度快生态丰富拥有大量的第三方库几乎可以解决任何问题易学易用学习曲线平缓适合快速原型开发数据科学和机器学习在数据处理、分析和机器学习领域有丰富的工具和库Rust 的优势性能优异编译为原生代码执行速度快内存安全所有权系统和借用检查器保证内存安全并发安全无数据竞争的并发编程系统级编程可以直接操作硬件和系统资源跨平台一次编译多处运行混合编程的优势性能关键部分用 Rust将计算密集型任务用 Rust 实现提高性能业务逻辑用 Python利用 Python 的开发效率和丰富的生态渐进式迁移可以逐步将 Python 代码迁移到 Rust而不是一次性重写充分利用现有代码可以在不放弃现有 Python 代码的情况下逐步引入 RustPython 与 Rust 交互的方式1. 使用 PyO3PyO3 是一个 Rust 库用于创建 Python 扩展模块。它允许你在 Rust 中定义 Python 可调用的函数和类型。安装 PyO3# 在 Cargo.toml 中添加 [dependencies] pyo3 { version 0.18, features [extension-module] } [lib] crate-type [cdylib]示例创建一个简单的 Rust 扩展use pyo3::prelude::*; /// 计算斐波那契数列 #[pyfunction] fn fibonacci(n: u64) - u64 { match n { 0 0, 1 1, _ fibonacci(n - 1) fibonacci(n - 2), } } /// 一个简单的加法函数 #[pyfunction] fna add(a: i32, b: i32) - i32 { a b } /// 定义 Python 模块 #[pymodule] fn rust_extension(_py: Python, m: PyModule) - PyResult() { m.add_function(wrap_pyfunction!(fibonacci, m)?)?; m.add_function(wrap_pyfunction!(add, m)?)?; Ok(() ) }构建和使用# 构建 cargo build --release # 将生成的 .so 文件重命名为 Python 可导入的名称 cp target/release/librust_extension.so rust_extension.so # 在 Python 中使用 import rust_extension print(rust_extension.add(1, 2)) # 输出: 3 print(rust_extension.fibonacci(10)) # 输出: 552. 使用 ctypesctypes 是 Python 的标准库用于调用 C 函数。由于 Rust 可以编译为 C 兼容的库我们可以使用 ctypes 来调用 Rust 函数。示例// src/lib.rs #[no_mangle] pub extern C fn add(a: i32, b: i32) - i32 { a b }# Cargo.toml [lib] crate-type [cdylib]# 使用 ctypes 调用 import ctypes # 加载 Rust 库 lib ctypes.CDLL(./target/release/libmy_lib.so) # 定义函数签名 lib.add.argtypes [ctypes.c_int, ctypes.c_int] lib.add.restype ctypes.c_int # 调用函数 result lib.add(1, 2) print(result) # 输出: 33. 使用 Rust-cpythonRust-cpython 是另一个用于 Python 和 Rust 交互的库提供了类似于 PyO3 的功能。4. 使用 subprocess对于简单的场景我们可以使用 subprocess 模块在 Python 中调用 Rust 可执行文件。示例// src/main.rs fn main() { let args: VecString std::env::args().collect(); if args.len() 3 { let a: i32 args[1].parse().unwrap(); let b: i32 args[2].parse().unwrap(); println!({}, a b); } }# 使用 subprocess 调用 import subprocess result subprocess.run([./target/release/add, 1, 2], capture_outputTrue, textTrue) print(result.stdout.strip()) # 输出: 3实战案例高性能数据处理需求分析假设我们需要处理一个大型 CSV 文件计算其中某一列的平均值。对于大型文件Python 的处理速度可能会比较慢我们可以使用 Rust 来加速这个过程。实现步骤创建 Rust 库实现 CSV 文件的读取和计算创建 Python 接口使用 PyO3 包装 Rust 函数在 Python 中使用调用 Rust 函数处理数据Rust 部分// src/lib.rs use pyo3::prelude::*; use csv::ReaderBuilder; use std::fs::File; #[pyfunction] pub fn calculate_average(file_path: str, column_index: usize) - PyResultf64 { let file File::open(file_path).map_err(|e| PyErr::new::pyo3::exceptions::PyIOError, _(e.to_string()))?; let mut rdr ReaderBuilder::new().has_headers(true).from_reader(file); let mut sum 0.0; let mut count 0; for result in rdr.records() { let record result.map_err(|e| PyErr::new::pyo3::exceptions::PyValueError, _(e.to_string()))?; if let Some(value) record.get(column_index) { if let Ok(num) value.parse::f64() { sum num; count 1; } } } if count 0 { return Err(PyErr::new::pyo3::exceptions::PyValueError, _(No valid numbers found in column)); } Ok(sum / count as f64) } #[pymodule] fn csv_processor(_py: Python, m: PyModule) - PyResult() { m.add_function(wrap_pyfunction!(calculate_average, m)?)?; Ok(() ) }# Cargo.toml [package] name csv-processor version 0.1.0 edition 2021 [dependencies] pyo3 { version 0.18, features [extension-module] } csv 1.2 [lib] crate-type [cdylib]Python 部分import csv_processor # 生成测试数据 import csv import random with open(test_data.csv, w, newline) as f: writer csv.writer(f) writer.writerow([id, value]) for i in range(1000000): writer.writerow([i, random.random() * 100]) # 使用 Rust 函数计算平均值 import time start_time time.time() average csv_processor.calculate_average(test_data.csv, 1) end_time time.time() print(f平均值: {average}) print(f处理时间: {end_time - start_time:.2f} 秒) # 与纯 Python 实现比较 start_time time.time() sum_val 0 count 0 with open(test_data.csv, r) as f: reader csv.reader(f) next(reader) # 跳过表头 for row in reader: sum_val float(row[1]) count 1 average_py sum_val / count end_time time.time() print(fPython 平均值: {average_py}) print(fPython 处理时间: {end_time - start_time:.2f} 秒)性能对比在处理 100 万行数据时Rust 实现的处理速度通常比纯 Python 实现快 5-10 倍具体取决于硬件和数据特性。实战案例Web 应用后端需求分析假设我们需要构建一个 Web 应用后端其中包含一些计算密集型的任务。我们可以使用 Python 的 Flask 框架处理 HTTP 请求而将计算密集型任务委托给 Rust 处理。实现步骤创建 Rust 库实现计算密集型任务创建 Python 接口使用 PyO3 包装 Rust 函数创建 Flask 应用处理 HTTP 请求并调用 Rust 函数Rust 部分// src/lib.rs use pyo3::prelude::*; #[pyfunction] pub fn compute_prime_numbers(limit: u64) - PyResultVecu64 { let mut primes Vec::new(); for num in 2..limit { if is_prime(num) { primes.push(num); } } Ok(primes) } fn is_prime(n: u64) - bool { if n 1 { return false; } for i in 2..(n as f64).sqrt() as u64 { if n % i 0 { return false; } } true } #[pymodule] fn prime_calculator(_py: Python, m: PyModule) - PyResult() { m.add_function(wrap_pyfunction!(compute_prime_numbers, m)?)?; Ok(() ) }Python 部分from flask import Flask, request, jsonify import prime_calculator app Flask(__name__) app.route(/api/primes, methods[GET]) def get_primes(): limit request.args.get(limit, typeint, default100) try: primes prime_calculator.compute_prime_numbers(limit) return jsonify({ limit: limit, primes: primes, count: len(primes) }) except Exception as e: return jsonify({error: str(e)}), 500 if __name__ __main__: app.run(debugTrue)常见问题与解决方案1. 类型转换问题Python 和 Rust 的类型系统不同需要进行类型转换。解决方案PyO3 提供了自动类型转换对于复杂类型可以使用IntoPy和FromPyObjecttraits 进行自定义转换。2. 内存管理问题Python 使用垃圾回收而 Rust 使用所有权系统需要注意内存管理。解决方案使用 PyO3 提供的Py类型和GILGuard来管理 Python 对象的生命周期。3. 错误处理问题Python 和 Rust 的错误处理方式不同。解决方案使用 PyO3 的PyResult和PyErr来在 Rust 和 Python 之间传递错误。4. 构建和部署问题混合 Python 和 Rust 代码的构建和部署比较复杂。解决方案使用maturin工具来简化构建和部署过程。# 安装 maturin pip install maturin # 构建和安装 maturin develop最佳实践明确职责划分将计算密集型任务交给 Rust将业务逻辑和胶水代码交给 Python。保持接口简单设计清晰、简单的接口减少 Python 和 Rust 之间的数据传输开销。使用成熟的库优先使用 PyO3 这样成熟的库来处理 Python 和 Rust 之间的交互。性能测试在混合编程之前先进行性能测试确保 Rust 实现确实能带来性能提升。文档和注释为 Rust 和 Python 代码都添加详细的文档和注释方便维护。版本兼容性注意 Python 和 Rust 版本的兼容性避免因版本问题导致的错误。总结Python 与 Rust 的混合编程是一种强大的开发方式它结合了 Python 的开发效率和 Rust 的性能优势。通过 PyO3、ctypes 等工具我们可以轻松实现 Python 和 Rust 之间的交互为我们的应用带来更好的性能和开发体验。虽然混合编程会增加一些复杂性但对于性能要求较高的应用来说这种复杂性是值得的。随着 Rust 生态的不断发展Python 与 Rust 的交互会变得越来越简单和高效。保持学习保持输出今天的 Python 与 Rust 混合编程实战文章就到这里希望对大家有所帮助。欢迎在评论区分享你的经验和问题我们一起进步参考资料PyO3 文档Rust 官方文档Python ctypes 文档maturin 文档后端转 Rust 的萌新ID 第一程序员——名字大人很菜暂时。正在跟所有权和生命周期死磕日常记录 Rust 学习路上的踩坑经验和啊哈时刻代码片段保证能跑。保持学习保持输出。欢迎大佬们轻喷也欢迎同好一起进步。

更多文章