pyo3 icon indicating copy to clipboard operation
pyo3 copied to clipboard

`Python<'_>` is not a valid argument to `async #[pyfunction]`s

Open davidhewitt opened this issue 1 month ago • 2 comments

The following code fails to compile:

#[pyfunction]
async fn none(py: Python<'_>) -> Bound<'_, PyAny> {
    py.None().into_bound(py)
}

The error message is:

error[E0521]: borrowed data escapes outside of function
 --> src/lib.rs:7:5
  |
7 |     #[pyfunction]
  |     ^^^^^^^^^^^^^
  |     |
  |     `py` is a reference that is only valid in the function body
  |     `py` escapes the function body here
  |     lifetime `'py` defined here
  |     argument requires that `'py` must outlive `'static`
  |
  = note: this error originates in the attribute macro `pyfunction` (in Nightly builds, run with -Z macro-backtrace for more info)

error: future cannot be sent between threads safely
  --> src/lib.rs:7:5
   |
 7 |     #[pyfunction]
   |     ^^^^^^^^^^^^^ future created by async block is not `Send`
   |
   = help: within `{async block@src/lib.rs:7:5: 7:18}`, the trait `Send` is not implemented for `*mut pyo3::Python<'static>`

davidhewitt avatar Dec 09 '25 11:12 davidhewitt

It seems to me that the Python token and all Bound<'py, T> can never be held across an await point, as that breaks the Send guarantee. I am also unsure whether that has interactions with the GIL.

But it's more complex than this because async #[pyfunction] are guaranteed (by the way we currently construct them) to be polled with a Python thread attached, so this feels like it should be legal code (the future only ever executes when attached to the thread).

davidhewitt avatar Dec 09 '25 11:12 davidhewitt

I think in the short term the only thing we can do is improve the error message and document what to do instead. Maybe in the long-term there it is possible to find a way to express a future which can only be polled when attached to a Python thread at the language level, where the future itself is Send even if Python<'_> is not.

davidhewitt avatar Dec 09 '25 11:12 davidhewitt