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.