【问题标题】:How to pass an async function as a parameter in Rust PyO3如何在 Rust PyO3 中将异步函数作为参数传递
【发布时间】:2021-05-25 10:45:52
【问题描述】:

当我们编写 vanilla rust 并且必须将异步函数作为参数传递给另一个函数时,我们执行以下操作:

pub f<F,'a>(
    test: &dyn Fn(&'a mut String, String, String, TcpStream) -> F,
) where
    F: Future<Output = ()> + 'a,

但是,当我对 #![pyfunction] 执行相同操作并期望获得异步 python 函数时,我遇到了错误。

e.g async def fn():
            ....

在阅读 PyO3 的文档时,我发现我可以将 PyAny 包含为参数。

但是,在实现以下功能时:

pub fn start_server(test: PyAny) {
  test.call0();
}

我收到以下错误。

[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`

如何在我的代码中实现这一点。如果这是不可能的,我会理解,如果是这种情况,我会请求您向我推荐一个替代方案。

更新:

我找到了另一种方法,我创建一个空结构并以下列方式调用该方法。但如果我能在不创建空结构的情况下通过,我将不胜感激。

#[pymethods]
impl Server {
    #[new]
    fn new() -> Self {
        Self {}
    }

    fn start(mut self_: PyRefMut<Self>, test: &PyAny) {
        test.call0();
    }
}

但是在将异步函数作为参数传递时会出现错误

RuntimeWarning: coroutine
  s.start(h)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback

【问题讨论】:

  • 您必须提供更多信息和确切的错误,否则人们将无法提供帮助。请参阅此对最小可重现示例的说明:stackoverflow.com/help/minimal-reproducible-example
  • @sebpuetz,我做了一些补充。如果我需要更多信息,请告诉我。

标签: python asynchronous rust async-await pyo3


【解决方案1】:

您的函数需要引用,即&amp;PyAnyPyAny 作为一个拥有的值没有实现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"

因此,将其移至 Server 上的方法的修复很可能不是修复,而只是巧合,因为您将 test 更改为 &amp;PyAny

a whole section in the PyO3 documentation关于集成Python和Rust async/await

【讨论】:

  • 即使将其更改为 &PyAny 也没有修复它并且给出了同样的错误。
  • 它在本地对我有用,我将编辑我的答案以包含完整的 Python 和 Rust 代码。
猜你喜欢
  • 2015-01-20
  • 2016-07-23
  • 2020-12-27
  • 1970-01-01
  • 1970-01-01
  • 2021-07-16
  • 1970-01-01
  • 1970-01-01
  • 2021-08-16
相关资源
最近更新 更多