【问题标题】:How to call Python async function from Rust?如何从 Rust 调用 Python 异步函数?
【发布时间】:2021-05-26 14:43:48
【问题描述】:

我已经阅读了这个答案(How to call Rust async method from Python?),而我想做的恰恰相反。

我想调用 Python 异步函数并在 tokio 的运行时等待它。有可能吗?

我已经尝试了一些,但我在输出中遇到了错误。

这就是我的 python 文件的样子:

import rust_package

async def h():
    print("message from coroutine")


print("Hello world")
s = rust_package.Server()
s.start(h)

这就是我的 lib.rs 的样子:

#[pyclass]
struct Server {}

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

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


        let f = pyo3_asyncio::into_future(test).unwrap();
        let rt = tokio::runtime::Runtime::new().unwrap();
        pyo3_asyncio::tokio::init(rt);
        Python::with_gil(|py| {
            pyo3_asyncio::tokio::run_until_complete(py, async move {
                tokio::time::sleep(Duration::from_secs(1)).await;
                f.await.unwrap();
                Ok(())
            })
            .unwrap();
        });
}

#[pymodule]
pub fn roadrunner(py: Python<'_>, m: &PyModule) -> PyResult<()> {
    m.add_class::<Server>()?;
    pyo3_asyncio::try_init(py);
    Ok(())
}

我收到以下错误:

Hello world
Exception in callback <builtins.PyEnsureFuture object a
t 0x10bc1bd20>()
handle: <Handle <builtins.PyEnsureFuture object at 0x10
bc1bd20>()>
Traceback (most recent call last):
  File "/usr/local/Cellar/python@3.9/3.9.5/Frameworks/P
ython.framework/Versions/3.9/lib/python3.9/asyncio/even
ts.py", line 80, in _run
    self._context.run(self._callback, *self._args)
  File "/usr/local/Cellar/python@3.9/3.9.5/Frameworks/P
ython.framework/Versions/3.9/lib/python3.9/asyncio/task
s.py", line 679, in ensure_future
    raise TypeError('An asyncio.Future, a coroutine or
an awaitable is '
TypeError: An asyncio.Future, a coroutine or an awaitab
le is required

我显然正在传递一个异步函数并将其转换为未来。我无法弄清楚我哪里出错了。我已多次阅读pyo3-async 的文档,但我仍然无法弄清楚。 非常感谢您的帮助。

提前致谢。

【问题讨论】:

  • s.start(h) 将函数传递给start,而不是协程。你试过s.start(h())吗?
  • 谢谢@sebpuetz。我在这个问题上被困了很多天,你帮了我很多。它解决了问题。

标签: python rust async-await rust-tokio pyo3


【解决方案1】:

正如@sebpuetz 所建议的,

我只需要 改变

s.start(h)

到

s.start(h())

因为 h 本身只是一个函数。 h() 是协程,是必填项。

【讨论】:

  • 这是 Rust 的好处 - 尽管编译器有时会令人沮丧,但它会在编译时捕获类似的东西!
猜你喜欢
  • 1970-01-01
  • 2019-01-16
  • 1970-01-01
  • 1970-01-01
  • 2020-10-13
  • 2019-09-02
  • 2020-04-20
  • 1970-01-01
  • 2021-02-10
相关资源
最近更新 更多