pub struct PyOnceLock<T> { /* private fields */ }
Expand description
An equivalent to std::sync::OnceLock
for initializing objects while attached to
the Python interpreter.
Unlike OnceLock<T>
, this type will not deadlock with the interpreter.
Before blocking calls the cell will detach from the runtime and then
re-attach once the cell is unblocked.
§Re-entrant initialization
Like OnceLock<T>
, it is an error to re-entrantly initialize a PyOnceLock<T>
. The exact
behavior in this case is not guaranteed, it may either deadlock or panic.
§Examples
The following example shows how to use PyOnceLock
to share a reference to a Python list
between threads:
use pyo3::sync::PyOnceLock;
use pyo3::prelude::*;
use pyo3::types::PyList;
static LIST_CELL: PyOnceLock<Py<PyList>> = PyOnceLock::new();
pub fn get_shared_list(py: Python<'_>) -> &Bound<'_, PyList> {
LIST_CELL
.get_or_init(py, || PyList::empty(py).unbind())
.bind(py)
}
Implementations§
Source§impl<T> PyOnceLock<T>
impl<T> PyOnceLock<T>
Sourcepub fn get(&self, _py: Python<'_>) -> Option<&T>
pub fn get(&self, _py: Python<'_>) -> Option<&T>
Get a reference to the contained value, or None
if the cell has not yet been written.
Sourcepub fn get_or_init<F>(&self, py: Python<'_>, f: F) -> &Twhere
F: FnOnce() -> T,
pub fn get_or_init<F>(&self, py: Python<'_>, f: F) -> &Twhere
F: FnOnce() -> T,
Get a reference to the contained value, initializing it if needed using the provided closure.
See the type-level documentation for detail on re-entrancy and concurrent initialization.
Sourcepub fn get_or_try_init<F, E>(&self, py: Python<'_>, f: F) -> Result<&T, E>
pub fn get_or_try_init<F, E>(&self, py: Python<'_>, f: F) -> Result<&T, E>
Like get_or_init
, but accepts a fallible initialization function. If it fails, the cell
is left uninitialized.
See the type-level documentation for detail on re-entrancy and concurrent initialization.
Sourcepub fn get_mut(&mut self) -> Option<&mut T>
pub fn get_mut(&mut self) -> Option<&mut T>
Get the contents of the cell mutably. This is only possible if the reference to the cell is unique.
Sourcepub fn set(&self, _py: Python<'_>, value: T) -> Result<(), T>
pub fn set(&self, _py: Python<'_>, value: T) -> Result<(), T>
Set the value in the cell.
If the cell has already been written, Err(value)
will be returned containing the new
value which was not written.
Sourcepub fn take(&mut self) -> Option<T>
pub fn take(&mut self) -> Option<T>
Takes the value out of the cell, moving it back to an uninitialized state.
Has no effect and returns None if the cell has not yet been written.
Sourcepub fn into_inner(self) -> Option<T>
pub fn into_inner(self) -> Option<T>
Consumes the cell, returning the wrapped value.
Returns None if the cell has not yet been written.
Source§impl<T> PyOnceLock<Py<T>>
impl<T> PyOnceLock<Py<T>>
Source§impl<T> PyOnceLock<Py<T>>where
T: PyTypeCheck,
impl<T> PyOnceLock<Py<T>>where
T: PyTypeCheck,
Sourcepub fn import<'py>(
&self,
py: Python<'py>,
module_name: &str,
attr_name: &str,
) -> PyResult<&Bound<'py, T>>
pub fn import<'py>( &self, py: Python<'py>, module_name: &str, attr_name: &str, ) -> PyResult<&Bound<'py, T>>
This is a shorthand method for get_or_init
which imports the type from Python on init.
§Example: Using PyOnceLock
to store a class in a static variable.
PyOnceLock
can be used to avoid importing a class multiple times:
#[pyfunction]
fn create_ordered_dict<'py>(py: Python<'py>, dict: Bound<'py, PyDict>) -> PyResult<Bound<'py, PyAny>> {
// Even if this function is called multiple times,
// the `OrderedDict` class will be imported only once.
static ORDERED_DICT: PyOnceLock<Py<PyType>> = PyOnceLock::new();
ORDERED_DICT
.import(py, "collections", "OrderedDict")?
.call1((dict,))
}