Skip to content
Advertisement

How to call Python async function from Rust?

I have read this answer(How to call Rust async method from Python?) and what I want to do is the opposite of this.

I want to call a Python async function and await it in tokio’s runtime. Is it possible?

I have given it some tries but I am facing an error in the output.

This is how my python file looks like:

import rust_package

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


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

and this is how my lib.rs looks like:

#[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(())
}

I am getting the following error:

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

I clearly am passing an async function and converting it to a future. I am unable to figure out where I am going wrong. I have read the documentation of pyo3-async multiple times but I am still unable to figure it out. I would really appreciate some help.

Thanks in advance.

Advertisement

Answer

As suggested by @sebpuetz ,

All I needed was to change

s.start(h)

to

s.start(h())

as h on its own is just a function. h() is a coroutine, which was the required item.

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement