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.
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.