[英]How to pass an async function as a parameter in Rust PyO3
When we write vanilla rust and we have to pass in an async function as an argument to another function we do the following:当我们编写 vanilla rust 并且我们必须将异步 function 作为参数传递给另一个 function 时,我们执行以下操作:
pub f<F,'a>(
test: &dyn Fn(&'a mut String, String, String, TcpStream) -> F,
) where
F: Future<Output = ()> + 'a,
But when I do the same on a #![pyfunction]
expecting to get an async python function, I am getting an error.但是,当我在
#![pyfunction]
上执行相同操作并期望获得异步python function 时,我遇到了错误。
e.g async def fn():
....
On reading the docs of PyO3, I found out that I can include PyAny
as a param.在阅读 PyO3 的文档时,我发现我可以将
PyAny
作为参数包含在内。
But, on implementing the following function:但是,在实现以下 function 时:
pub fn start_server(test: PyAny) {
test.call0();
}
I get the following error.我收到以下错误。
[rustc E0277] [E] the trait bound `pyo3::PyAny: pyo3::FromPyObject<'_>` is not satisfied
expected an implementor of trait `pyo3::FromPyObject<'_>`
note: required because of the requirements on the impl of `pyo3::FromPyObject<'_>` for `pyo3::PyAny`
How can I implement this in my code.如何在我的代码中实现这一点。 I would understand if this is not possible, if that is the case, I would request you to please recommend me an alternative.
如果这是不可能的,我会理解,如果是这种情况,我会要求您向我推荐一个替代方案。
UPDATE:更新:
I have found an alternative where I create an empty struct and call the method in the following way.我找到了另一种方法,我创建一个空结构并以下列方式调用该方法。 But I would really appreciate if I can get through without creating an empty struct.
但如果我能在不创建空结构的情况下通过,我将不胜感激。
#[pymethods]
impl Server {
#[new]
fn new() -> Self {
Self {}
}
fn start(mut self_: PyRefMut<Self>, test: &PyAny) {
test.call0();
}
}
But on passing an async function as param gives an error of但是在将异步 function 作为参数传递时,会出现错误
RuntimeWarning: coroutine
s.start(h)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
Your function needs to take a reference, ie &PyAny
.您的 function 需要参考,即
&PyAny
。 PyAny
as an owned value does not implement FromPyObject
, which is why you got the error. PyAny
作为拥有值不实现FromPyObject
,这就是您收到错误的原因。
// lib.rs
use pyo3::prelude::*;
use pyo3::wrap_pyfunction;
#[pyfunction]
fn foo(x: &PyAny) -> PyResult<&PyAny> {
x.call0()
}
#[pymodule]
fn async_pyo3(py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(foo, m)?).unwrap();
Ok(())
}
import async_pyo3
async def bar():
return "foo"
awaitable = async_pyo3.foo(bar) # <coroutine object bar at 0x7f8f6aa01340>
print(await awaitable) # "foo"
As such, the fix of moving it to an method on Server
most likely was not the fix, but just coincidence since you changed test
to &PyAny
.因此,将其移动到
Server
上的方法的修复很可能不是修复,而只是巧合,因为您将test
更改为&PyAny
。
There is a whole section in the PyO3 documentation about integrating Python and Rust async / await PyO3 文档中有一整节关于集成 Python 和 Rust async / await
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.