Function pyo3_asyncio::tokio::future_into_py_with_locals
source · pub fn future_into_py_with_locals<F, T>(
py: Python<'_>,
locals: TaskLocals,
fut: F
) -> PyResult<&PyAny>where
F: Future<Output = PyResult<T>> + Send + 'static,
T: IntoPy<PyObject>,
Expand description
Convert a Rust Future into a Python awaitable
If the asyncio.Future
returned by this conversion is cancelled via asyncio.Future.cancel
,
the Rust future will be cancelled as well (new behaviour in v0.15
).
Python contextvars
are preserved when calling async Python functions within the Rust future
via into_future
(new behaviour in v0.15
).
Although
contextvars
are preserved for async Python functions, synchronous functions will unfortunately fail to resolve them when called within the Rust future. This is because the function is being called from a Rust thread, not inside an actual Python coroutine context.As a workaround, you can get the
contextvars
from the current task locals usingget_current_locals
andTaskLocals::context
, then wrap your synchronous function in a call tocontextvars.Context.run
. This will set the context, call the synchronous function, and restore the previous context when it returns or raises an exception.
Arguments
py
- PyO3 GIL guardlocals
- The task locals for the given futurefut
- The Rust future to be converted
Examples
use std::time::Duration;
use pyo3::prelude::*;
/// Awaitable sleep function
#[pyfunction]
fn sleep_for<'p>(py: Python<'p>, secs: &'p PyAny) -> PyResult<&'p PyAny> {
let secs = secs.extract()?;
pyo3_asyncio::tokio::future_into_py_with_locals(
py,
pyo3_asyncio::tokio::get_current_locals(py)?,
async move {
tokio::time::sleep(Duration::from_secs(secs)).await;
Python::with_gil(|py| Ok(py.None()))
}
)
}