使用 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}