使用 Rust 扩展 Robyn
- PyO3 Bridge
- 示例:一个简单的Rust扩展
- 1、安装必须的组件
- 2、初始化Rust项目
- 3、编写Rust代码
- 4、在Robyn中使用Rust代码
在“Robyn高性能Web框架系列07:多进程、性能调优”一节中,我们讲解了Robyn丰富的性能调优方式,其中也详细说明了其独特的“Python-Rust 混合架构”即Python层负责业务逻辑,Rust层负责性能调优,Python层与Rust层通过PyO3有机结合,这样既可以获得Python易开发性与 Rust 的高性能。本节将通过一个小示例来讲解如何使用 Rust 扩展 Robyn。
PyO3 Bridge
在Robyn提供了一些Rust扩展机制,如--create-rust-file
命令与--compile-rust-path
命令,然而这些命令不是很好用。既然Robyn是基于PyO3实现的“Python-Rust 混合架构”,那么我们就直接通过PyO3来完成使用 Rust 对Robyn的扩展。
PyO3 是一个用于将 Python 与 Rust 集成的库,支持Python与Rust的双向互调用:
- 在 Rust 中编写 Python 模块(作为扩展模块),供 Python 调用。
- 在 Rust 中嵌入 Python 解释器,让 Rust 调用 Python 代码。
当然,PyO3本身就是一个复杂、完善的工具,本节并不打算深入讲解PyO3,有兴趣的小伙伴可以关注GeekABC后续的文章。
示例:一个简单的Rust扩展
在计算机图形学(Computer Graphics) 中,三角形面积计算有非常广泛的用途,因此提高三角形面积计算的性能有很大的意义。在本示例中,我们将使用Robyn的Python层来接收用户输入的“高”和“底边”的长度,使用Rust 层来完成面积计算,返回给Python层,最后返回给用户。
1、安装必须的组件
Rust 开发环境
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
安装后运行:
rustc --version
cargo --version
确保 Rust 和 Cargo 已可用。
Python 环境
需要安装与目标编译版本匹配的 Python 解释器:
- 推荐使用 pyenv 或虚拟环境(venv, conda);
- python3-dev / python3.X-dev(Linux)版本必须存在;
- 可支持多个 Python 版本(构建时指定)。
maturin——构建与发布工具
maturin
它是一个用于以最低配置构建和发布基于 Rust 的 Python 包的工具。
pip install maturin
最好进行验证:
maturin --version
在不同的环境中安装上述组件时可能会有具体问题,请根据实际情况进行调整。
2、初始化Rust项目
Rust项目可以作为一个独立项目,也可以直接放在Robyn项目的特定位置,如src/components
下。使用maturin init
命令初始化项目:
cd src/components/triangle_area
maturin init
✔ 🤷 What kind of bindings to use? · pyo3✨ Done! New project created triangle_area
这时会产生一个类似的项目结构:
src
├── app.py
├── components├── triangle_area├── src├── lib.rs├── Cargo.toml├── pyproject.toml
3、编写Rust代码
Cargo.toml
[package]
name = "triangle_area"
version = "0.1.0"
edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
name = "triangle_area"
crate-type = ["cdylib"] [dependencies]
pyo3 = "0.25.0"
必须保持package
和lib
的name一致。
src/lib.rs
use pyo3::prelude::*; /// Formats the sum of two numbers as string.
#[pyfunction]
fn area_by_base_height(base: f64, height: f64) -> PyResult<f64> { Ok(0.5 * base * height)
} /// A Python module implemented in Rust.
#[pymodule]
fn triangle_area(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(area_by_base_height, m)?)?; Ok(())
}
必须保持pymodule的name与Cargo.toml中的package
和lib
的name一致。
4、在Robyn中使用Rust代码
完成代码编写后,运行maturin develop
命令,这将构建软件包并将其安装到之前创建并激活的 Python 虚拟环境中。这时我们就可以在Robyn项目中使用import triangle_area
引入该库了。
from robyn import Robyn, Request
from robyn.types import PathParams import triangle_area app = Robyn(__file__) @app.get("/calc_triangle_area/:base/:height")
def calc_triangle_area(request: Request,path_params: PathParams): try: r = triangle_area.area_by_base_height( base=float(path_params.get("base",0.0)), height=float(path_params.get("height",0.0)) ) except: return {"message": "Invalid input for base or height"} return {"message": r}