使用PyO3從Python呼叫 Rust:加速Python

banq發表於2021-11-25

使用 Rust 加速你的 Python:PyO3使從 Python 呼叫 Rust 程式碼變得容易。您可以編寫 Rust 庫,並依靠 PyO3 和生態系統中maturin的支援工具的組合PyO3來編譯 Rust 庫並將其作為 Python 模組直接安裝。其中,PyO3 可以在 Python 和 Rust 之間轉換型別,並且可以透過一組宏輕鬆地將 Rust 函式匯出到 Python。
在這篇博文中,我將簡要介紹 PyO3。之後,我將討論幾個用 Rust 編寫並從 Python 呼叫的示例函式。這些例子包括:
  • 在 Python 和 Rust 中計算第 n 個斐波那契數
  • 讓 Python 在 Rust 函式中使用多種型別
  • 在 Python 程式碼中使用 Rust 結構
  • 使用 Python 將 JSON 傳送到 Rust 並將該 JSON 序列化為結構
  • 允許 Rust 從 Python 執行時使用記錄器
  • 在 Rust 中生成錯誤並將其作為異常在 Python 中捕獲

 

PyO3 簡介
PyO3 為想要將 Rust 和 Python 程式碼粘合在一起的人們提供了一些人體工程學設計。它可以幫助您從 Rust 呼叫 Python 程式碼以及從 Python 呼叫 Rust 程式碼。由於我只使用它從 Python 呼叫 Rust 程式碼,這是我在這裡寫的唯一內容。
那麼 PyO3 給你什麼?
首先,有maturin。該工具將為您編譯 Rust 程式碼,並將編譯後的程式碼作為 Python 模組安裝在您的虛擬環境中。之後,您可以在 Python 程式碼中匯入此模組並使用它。在您pip install maturin 之後,您只需要執行 1 個命令 ( maturin develop ) 即可在 Python 中使用 Rust 程式碼。
除了maturin,當然還有 PyO3 本身。PyO3 為 Python 直譯器提供 Rust 繫結。這使得您不必真正為 Python 和 Rust 之間的互動而煩惱。例如,您不必擔心如何在 C 中將 Python 字串轉換為某些內容,然後在 Rust 中再次轉換為其他內容。整數、浮點數、列表、字典等也是如此。為了方便起見,PyO3 附帶了許多宏,可以防止您編寫過多的樣板程式碼。要將 Rust 函式公開給 Python,您可以使用宏註釋它們。在此之後,PyO3 將負責其餘的工作。如果您想匯出結構或方法,這同樣適用。
 

從 Python 呼叫 Rust 函式
在第一個示例中,我們將從 Python 呼叫 Rust 乘法函式。通常,我們可以這樣寫:

fn multiply(a: isize, b: isize) -> isize {
    a * b
}


在不新增太多東西的情況下,我們可以讓這個函式從 Python 中呼叫。首先,我們需要:
  • 引入pyo3 prelude
  • 註釋函式#[pyfunction]以將其轉換為 PyCFunction
  • 將結果包裝在一個 PyResult
  • 將函式新增到 #[pymodule]

下面的程式碼以相同的順序說明了上述步驟:

use pyo3::prelude::*;

#[pyfunction]
fn multiply(a: isize, b: isize) -> PyResult<isize> {
    Ok(a * b)
}

#[pymodule]
fn rust(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_function(wrap_pyfunction!(multiply, m)?)?;
    Ok(())
}


以上將在一個名為rust(在最後一個函式的名稱之後)的Python 模組中公開乘法函式。我們還需要放置適當的Cargo.toml檔案。
為方便起見,請確保 Cargo.toml 中庫的名稱與使用#[pymodule]. 在我的示例中,我將以下內容放入我的Cargo.toml:

[lib]
name = "rust"




當這兩個名稱匹配時,maturin構建工具將使用該名稱將 Rust 庫安裝為 Python 模組。
因此,在這種情況下,選擇rust作為包的名稱,我們可以編寫以下 Python 來呼叫乘法函式:

import rust

result = rust.multiply(2, 3)
print(result)


為了能夠執行此程式碼,我們需要編譯 Rust 程式碼並將其安裝為 Python 庫。這是maturin進來的地方:

root@rust:/# git clone https://github.com/saidvandeklundert/pyo3.git
Cloning into 'pyo3'...
remote: Enumerating objects: 36, done.
    ...
Resolving deltas: 100% (9/9), done.
root@rust:/# cd pyo3/multiply/
root@rust:/pyo3/multiply# python3 -m venv .env
root@rust:/pyo3/multiply# source .env/bin/activate
(.env) root@rust:/pyo3/multiply# pip install maturin
Collecting maturin
    ...
Installing collected packages: toml, maturin
Successfully installed maturin-0.11.5 toml-0.10.2
(.env) root@rust:/pyo3/multiply# maturin develop
 Found pyo3 bindings
 Found CPython 3.9 at python
   Compiling proc-macro2 v1.0.32
    ...
   Compiling multiply v0.1.0 (/pyo3/multiply)
    Finished dev [unoptimized + debuginfo] target(s) in 23.48s
(.env) root@rust:/pyo3/multiply# python3 multiply.py
6


現在我可以執行這個指令碼::

(.env) root@rust: multiply# python3 multiply.py
6

更多點選標題

相關文章