[英]How to call Rust async method from Python?
我想在 Python 中使用 Rust 異步方法。 我正在嘗試使用PyO3或rust-cpython 。
例如,對於同步 Rust 功能,我可以使用,
#[pyfunction]
fn myfunc(a: String) -> PyResult<String> {
let mut contents = String::new();
contents = a.to_string() + " appended";
Ok((contents))
}
#[pymodule]
fn MyModule(py: Python, m: &PyModule) -> PyResult<()> {
m.add_wrapped(wrap_pyfunction!(urlshot))?;
Ok(())
}
對於異步方法,我該怎么做? 比如我想在Python中調用如下方法,
async fn hello_world() {
println!("hello, world!");
}
由於沒有簡單的方法來解決這個問題(至少,我沒有找到),我將我的異步方法轉換為同步方法。 並在 Python 方面將其稱為,
async fn my_method(s: &str) -> Result<String, Error> {
// do something
}
#[pyfunction]
fn my_sync_method(s: String) -> PyResult<String> {
let mut rt = tokio::runtime::Runtime::new().unwrap();
let mut contents = String::new();
rt.block_on(async {
result = format!("{}", my_sync_method(&s).await.unwrap()).to_string();
});
Ok((result))
}
#[pymodule]
fn MyModule(py: Python, m: &PyModule) -> PyResult<()> {
m.add_wrapped(wrap_pyfunction!(my_sync_method))?;
Ok(())
}
在Cargo.toml
文件中,我添加了以下依賴項,
[dependencies.pyo3]
git = "https://github.com/PyO3/pyo3"
features = ["extension-module"]
運行cargo build --release
后,會生成target/release/libMyModule.so
二進制文件。 將其重命名為MyModule.so
,現在可以從 Python 導入。
import MyModule
result = MyModule.my_sync_method("hello")
使用setuptools-rust ,我可以將其捆綁為普通的 Python package。
以上所有代碼和命令都在新發布的 Linux Mint 20 上進行了測試。在 MacOS 上,二進制文件將為libMyModule.dylib
。
如果你想使用 Python 來控制 Rust 的異步 function,我認為它不會起作用(或者至少它很復雜,因為你需要連接兩個不同future
機制)。 對於異步函數,Rust 編譯器將維護一個 state 機器來管理在 await 的控制下正確運行的協程。 這是 Rust 應用程序的內部 state 並且 Python 無法觸摸它。 同樣Python解釋器也有一個state機器不能被Rust觸及。
我確實找到了有關如何使用 FFI 導出異步 function 的主題。 主要思想是將異步包裝在BoxFuture
中,並讓 C 控制將其返回到 Rust 的時間。 但是,您不能在 PyO3 中使用BoxFuture
,因為它的pyfunction
宏無法將 function 返回BoxFuture
轉換為 Python 回調。 您可以嘗試使用 FFI 創建一個庫並使用 python 的 cffi 模塊來加載它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.