PyO3Python 解釋器的 Rust 綁定
PyO3 是 Python 的 Rust 綁定,可以用 Rust 語言對 Python 加速。這包括用 Rust 語言運行 Python 代碼并與之交互,以及直接編寫原生 Python 模塊。
PyO3 一開始只是作為 rust-cpython 的分支出現(xiàn), 后來由于 rust-cpython 缺乏維護, PyO3 開始在 Rust 社區(qū)流行, 隨著時間推移 PyO3 與 rust-cpython 有了根本的差異。由于導出包使用 Rust 語言開發(fā),以及 Rust 語言速度快且內(nèi)存利用率極高,因此在運行效率及性能上優(yōu)于同等 Python 實現(xiàn)模塊。
用法:
PyO3 支持 Python 2.7 和 Python 3.6 及更高版本,Rust 最低版本要求則是 1.45.0。
對于使用 Python 3.6 的用戶而言,也可以使用 PyPy 進行構(gòu)建(通過 cpyext),PyPy 版本要求為 7.3 及以上。詳情可以參閱指南中的 pypy 部分。
安裝完成之后,就可以在 Rust 中編寫原生 Python 模塊,也可以在 Rust 二進制文件中使用 Python。
在部分操作系統(tǒng)上,如 Ubuntu 18.04,則需要依賴一些其他軟件包所提供的環(huán)境,針對這些系統(tǒng)需要運行以下命令:
sudo apt install python3-dev python-dev
在 Python 使用 Rust:
PyO3 可用于生成本地 Python 模塊。
Cargo.toml
[package] name = "string-sum" version = "0.1.0" edition = "2018" [lib] name = "string_sum" # "cdylib" is necessary to produce a shared library for Python to import from. # # Downstream Rust code (including code in `bin/`, `examples/`, and `tests/`) will not be able # to `use string_sum;` unless the "rlib" or "lib" crate type is also included, e.g.: # crate-type = ["cdylib", "rlib"] crate-type = ["cdylib"] [dependencies.pyo3] version = "0.13.1" features = ["extension-module"]
src/lib.rs
use pyo3::prelude::*;
use pyo3::wrap_pyfunction;
/// Formats the sum of two numbers as string.
#[pyfunction]
fn sum_as_string(a: usize, b: usize) -> PyResult<String> {
Ok((a + b).to_string())
}
/// A Python module implemented in Rust.
#[pymodule]
fn string_sum(py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(sum_as_string, m)?)?;
Ok(())
}
在 Windows 和 Linux 上,可以使用命令cargo build --release正常構(gòu)建。在 macOS 上,則需要設置其他鏈接器參數(shù)。一種選擇是使用cargo rustc --release -- -C link-arg=-undefined -C link-arg=dynamic_lookup進行編譯,另一種方法是使用以下命令創(chuàng)建一個.cargo/config:
[target.x86_64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] [target.aarch64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ]
在開發(fā)時,
https://unsplash.com/collections/97745155/
https://unsplash.com/collections/55327332/
https://unsplash.com/collections/18738157/
https://unsplash.com/collections/83253510/
https://unsplash.com/collections/85028995/
https://unsplash.com/collections/73694405/
https://unsplash.com/collections/73980211/
可以符號鏈接或復制(符號鏈接 symlink,又稱軟連接)并重新命名目標文件夾的共享庫;在 macOS 中,將libstring_sum.dylib重命名為string_sum.so,在 Windows 上將libstring_sum.dll重命名為string_sum.pyd以及在 Linux 上將libstring_sum.so重命名為string_sum.so。然后在同一文件夾中打開一個 Python shell,就能夠進行import string_sum操作。
可以使用 maturin 或 setuptools-rust 來構(gòu)建、測試和發(fā)布你創(chuàng)建的 Python 模塊。具體的 setuptools-rust 示范用例可以在 examples / word-count 中找到,而 maturin 則無需任何配置即可直接使用。
在 Rust 使用 Python:
如果你想要用 Rust 應用程序在內(nèi)部創(chuàng)建一個 Python 解釋器并使用它來運行Python代碼,那么將pyo3按照如下方式添加進Cargo.toml:
[dependencies.pyo3] version = "0.13.1" features = ["auto-initialize"]
示例程序顯示了sys.version的值和當前用戶名:
use pyo3::prelude::*;
use pyo3::types::IntoPyDict;
fn main() -> Result<(), ()> {
Python::with_gil(|py| {
main_(py).map_err(|e| {
// We can't display Python exceptions via std::fmt::Display,
// so print the error here manually.
e.print_and_set_sys_last_vars(py);
})
})
}
fn main_(py: Python) -> PyResult<()> {
let sys = py.import("sys")?;
let version: String = sys.get("version")?.extract()?;
let locals = [("os", py.import("os")?)].into_py_dict(py);
let code = "os.getenv('USER') or os.getenv('USERNAME') or 'Unknown'";
let user: String = py.eval(code, None, Some(&locals))?.extract()?;
println!("Hello {}, I'm Python {}", user, version);
Ok(())
}
更多關于 PyO3 的示例,可以查看官方指南。
