pub struct Python<'py>(/* private fields */);
Expand description
A marker token that represents holding the GIL.
It serves three main purposes:
- It provides a global API for the Python interpreter, such as
Python::eval_bound
. - It can be passed to functions that require a proof of holding the GIL, such as
Py::clone_ref
. - Its lifetime represents the scope of holding the GIL which can be used to create Rust
references that are bound to it, such as [
Bound<'py, PyAny>
].
Note that there are some caveats to using it that you might need to be aware of. See the Deadlocks and Releasing and freeing memory paragraphs for more information about that.
§Obtaining a Python token
The following are the recommended ways to obtain a [Python<'py>
] token, in order of preference:
- If you already have something with a lifetime bound to the GIL, such as [
Bound<'py, PyAny>
], you can use its.py()
method to get a token. - In a function or method annotated with
#[pyfunction]
or#[pymethods]
you can declare it as a parameter, and PyO3 will pass in the token when Python code calls it. - When you need to acquire the GIL yourself, such as when calling Python code from Rust, you
should call
Python::with_gil
to do that and pass your code as a closure to it.
The first two options are zero-cost; Python::with_gil
requires runtime checking and may need to block
to acquire the GIL.
§Deadlocks
Note that the GIL can be temporarily released by the Python interpreter during a function call (e.g. importing a module). In general, you don’t need to worry about this because the GIL is reacquired before returning to the Rust code:
`Python` exists |=====================================|
GIL actually held |==========| |================|
Rust code running |=======| |==| |======|
This behaviour can cause deadlocks when trying to lock a Rust mutex while holding the GIL:
- Thread 1 acquires the GIL
- Thread 1 locks a mutex
- Thread 1 makes a call into the Python interpreter which releases the GIL
- Thread 2 acquires the GIL
- Thread 2 tries to locks the mutex, blocks
- Thread 1’s Python interpreter call blocks trying to reacquire the GIL held by thread 2
To avoid deadlocking, you should release the GIL before trying to lock a mutex or await
ing in
asynchronous code, e.g. with Python::allow_threads
.
§Releasing and freeing memory
The [Python<'py>
] type can be used to create references to variables owned by the Python
interpreter, using functions such as Python::eval_bound
and PyModule::import_bound
.
Implementations§
source§impl Python<'_>
impl Python<'_>
sourcepub fn with_gil<F, R>(f: F) -> R
pub fn with_gil<F, R>(f: F) -> R
Acquires the global interpreter lock, allowing access to the Python interpreter. The
provided closure F
will be executed with the acquired Python
marker token.
If implementing #[pymethods]
or #[pyfunction]
,
declare py: Python
as an argument. PyO3 will pass in the token to grant access to the GIL
context in which the function is running, avoiding the need to call with_gil
.
If the auto-initialize
feature is enabled and the Python runtime is not already
initialized, this function will initialize it. See
prepare_freethreaded_python
for details.
If the current thread does not yet have a Python “thread state” associated with it,
a new one will be automatically created before F
is executed and destroyed after F
completes.
§Panics
- If the
auto-initialize
feature is not enabled and the Python interpreter is not initialized.
§Examples
use pyo3::prelude::*;
Python::with_gil(|py| -> PyResult<()> {
let x: i32 = py.eval_bound("5", None, None)?.extract()?;
assert_eq!(x, 5);
Ok(())
})
sourcepub unsafe fn with_gil_unchecked<F, R>(f: F) -> R
pub unsafe fn with_gil_unchecked<F, R>(f: F) -> R
Like Python::with_gil
except Python interpreter state checking is skipped.
Normally when the GIL is acquired, we check that the Python interpreter is an appropriate state (e.g. it is fully initialized). This function skips those checks.
§Safety
If Python::with_gil
would succeed, it is safe to call this function.
In most cases, you should use Python::with_gil
.
A justified scenario for calling this function is during multi-phase interpreter
initialization when Python::with_gil
would fail before
_Py_InitializeMain
is called because the interpreter is only partially initialized.
Behavior in other scenarios is not documented.
source§impl<'py> Python<'py>
impl<'py> Python<'py>
sourcepub fn allow_threads<T, F>(self, f: F) -> T
pub fn allow_threads<T, F>(self, f: F) -> T
Temporarily releases the GIL, thus allowing other Python threads to run. The GIL will be
reacquired when F
’s scope ends.
If you don’t need to touch the Python interpreter for some time and have other Python threads around, this will let you run Rust-only code while letting those other Python threads make progress.
Only types that implement Ungil
can cross the closure. See the
module level documentation for more information.
If you need to pass Python objects into the closure you can use Py
<T>
to create a
reference independent of the GIL lifetime. However, you cannot do much with those without a
Python
token, for which you’d need to reacquire the GIL.
§Example: Releasing the GIL while running a computation in Rust-only code
use pyo3::prelude::*;
#[pyfunction]
fn sum_numbers(py: Python<'_>, numbers: Vec<u32>) -> PyResult<u32> {
// We release the GIL here so any other Python threads get a chance to run.
py.allow_threads(move || {
// An example of an "expensive" Rust calculation
let sum = numbers.iter().sum();
Ok(sum)
})
}
Please see the Parallelism chapter of the guide for a thorough discussion of using
Python::allow_threads
in this manner.
§Example: Passing borrowed Python references into the closure is not allowed
use pyo3::prelude::*;
use pyo3::types::PyString;
fn parallel_print(py: Python<'_>) {
let s = PyString::new_bound(py, "This object cannot be accessed without holding the GIL >_<");
py.allow_threads(move || {
println!("{:?}", s); // This causes a compile error.
});
}
sourcepub fn eval(
self,
code: &str,
globals: Option<&'py PyDict>,
locals: Option<&'py PyDict>,
) -> PyResult<&'py PyAny>
👎Deprecated since 0.21.0: Python::eval
will be replaced by Python::eval_bound
in a future PyO3 versionAvailable on crate feature gil-refs
only.
pub fn eval( self, code: &str, globals: Option<&'py PyDict>, locals: Option<&'py PyDict>, ) -> PyResult<&'py PyAny>
Python::eval
will be replaced by Python::eval_bound
in a future PyO3 versiongil-refs
only.Deprecated version of Python::eval_bound
sourcepub fn eval_bound(
self,
code: &str,
globals: Option<&Bound<'py, PyDict>>,
locals: Option<&Bound<'py, PyDict>>,
) -> PyResult<Bound<'py, PyAny>>
pub fn eval_bound( self, code: &str, globals: Option<&Bound<'py, PyDict>>, locals: Option<&Bound<'py, PyDict>>, ) -> PyResult<Bound<'py, PyAny>>
Evaluates a Python expression in the given context and returns the result.
If globals
is None
, it defaults to Python module __main__
.
If locals
is None
, it defaults to the value of globals
.
If globals
doesn’t contain __builtins__
, default __builtins__
will be added automatically.
§Examples
let result = py.eval_bound("[i * 10 for i in range(5)]", None, None).unwrap();
let res: Vec<i64> = result.extract().unwrap();
assert_eq!(res, vec![0, 10, 20, 30, 40])
sourcepub fn run(
self,
code: &str,
globals: Option<&PyDict>,
locals: Option<&PyDict>,
) -> PyResult<()>
👎Deprecated since 0.21.0: Python::run
will be replaced by Python::run_bound
in a future PyO3 versionAvailable on crate feature gil-refs
only.
pub fn run( self, code: &str, globals: Option<&PyDict>, locals: Option<&PyDict>, ) -> PyResult<()>
Python::run
will be replaced by Python::run_bound
in a future PyO3 versiongil-refs
only.Deprecated version of Python::run_bound
sourcepub fn run_bound(
self,
code: &str,
globals: Option<&Bound<'py, PyDict>>,
locals: Option<&Bound<'py, PyDict>>,
) -> PyResult<()>
pub fn run_bound( self, code: &str, globals: Option<&Bound<'py, PyDict>>, locals: Option<&Bound<'py, PyDict>>, ) -> PyResult<()>
Executes one or more Python statements in the given context.
If globals
is None
, it defaults to Python module __main__
.
If locals
is None
, it defaults to the value of globals
.
If globals
doesn’t contain __builtins__
, default __builtins__
will be added automatically.
§Examples
use pyo3::{
prelude::*,
types::{PyBytes, PyDict},
};
Python::with_gil(|py| {
let locals = PyDict::new_bound(py);
py.run_bound(
r#"
import base64
s = 'Hello Rust!'
ret = base64.b64encode(s.encode('utf-8'))
"#,
None,
Some(&locals),
)
.unwrap();
let ret = locals.get_item("ret").unwrap().unwrap();
let b64 = ret.downcast::<PyBytes>().unwrap();
assert_eq!(b64.as_bytes(), b"SGVsbG8gUnVzdCE=");
});
You can use py_run!
for a handy alternative of run
if you don’t need globals
and unwrapping is OK.
sourcepub fn get_type<T>(self) -> &'py PyTypewhere
T: PyTypeInfo,
👎Deprecated since 0.21.0: Python::get_type
will be replaced by Python::get_type_bound
in a future PyO3 versionAvailable on crate feature gil-refs
only.
pub fn get_type<T>(self) -> &'py PyTypewhere
T: PyTypeInfo,
Python::get_type
will be replaced by Python::get_type_bound
in a future PyO3 versiongil-refs
only.Gets the Python type object for type T
.
sourcepub fn get_type_bound<T>(self) -> Bound<'py, PyType>where
T: PyTypeInfo,
pub fn get_type_bound<T>(self) -> Bound<'py, PyType>where
T: PyTypeInfo,
Gets the Python type object for type T
.
sourcepub fn import<N>(self, name: N) -> PyResult<&'py PyModule>
👎Deprecated since 0.21.0: Python::import
will be replaced by Python::import_bound
in a future PyO3 versionAvailable on crate feature gil-refs
only.
pub fn import<N>(self, name: N) -> PyResult<&'py PyModule>
Python::import
will be replaced by Python::import_bound
in a future PyO3 versiongil-refs
only.Deprecated form of Python::import_bound
sourcepub fn import_bound<N>(self, name: N) -> PyResult<Bound<'py, PyModule>>
pub fn import_bound<N>(self, name: N) -> PyResult<Bound<'py, PyModule>>
Imports the Python module with the specified name.
sourcepub fn NotImplemented(self) -> PyObject
pub fn NotImplemented(self) -> PyObject
Gets the Python builtin value NotImplemented
.
sourcepub fn version(self) -> &'py str
pub fn version(self) -> &'py str
Gets the running Python interpreter version as a string.
§Examples
Python::with_gil(|py| {
// The full string could be, for example:
// "3.10.0 (tags/v3.10.0:b494f59, Oct 4 2021, 19:00:18) [MSC v.1929 64 bit (AMD64)]"
assert!(py.version().starts_with("3."));
});
sourcepub fn version_info(self) -> PythonVersionInfo<'py>
pub fn version_info(self) -> PythonVersionInfo<'py>
Gets the running Python interpreter version as a struct similar to
sys.version_info
.
§Examples
Python::with_gil(|py| {
// PyO3 supports Python 3.7 and up.
assert!(py.version_info() >= (3, 7));
assert!(py.version_info() >= (3, 7, 0));
});
sourcepub fn checked_cast_as<T>(
self,
obj: PyObject,
) -> Result<&'py T, PyDowncastError<'py>>where
T: PyTypeCheck<AsRefTarget = T>,
👎Deprecated since 0.21.0: use obj.downcast_bound::<T>(py)
instead of py.checked_cast_as::<T>(obj)
Available on crate feature gil-refs
only.
pub fn checked_cast_as<T>(
self,
obj: PyObject,
) -> Result<&'py T, PyDowncastError<'py>>where
T: PyTypeCheck<AsRefTarget = T>,
obj.downcast_bound::<T>(py)
instead of py.checked_cast_as::<T>(obj)
gil-refs
only.Registers the object in the release pool, and tries to downcast to specific type.
sourcepub unsafe fn cast_as<T>(self, obj: PyObject) -> &'py Twhere
T: HasPyGilRef<AsRefTarget = T>,
👎Deprecated since 0.21.0: use obj.downcast_bound_unchecked::<T>(py)
instead of py.cast_as::<T>(obj)
Available on crate feature gil-refs
only.
pub unsafe fn cast_as<T>(self, obj: PyObject) -> &'py Twhere
T: HasPyGilRef<AsRefTarget = T>,
obj.downcast_bound_unchecked::<T>(py)
instead of py.cast_as::<T>(obj)
gil-refs
only.Registers the object in the release pool, and does an unchecked downcast to the specific type.
§Safety
Callers must ensure that ensure that the cast is valid.
sourcepub unsafe fn from_owned_ptr<T>(self, ptr: *mut PyObject) -> &'py Twhere
T: FromPyPointer<'py>,
👎Deprecated since 0.21.0: use Py::from_owned_ptr(py, ptr)
or Bound::from_owned_ptr(py, ptr)
insteadAvailable on crate feature gil-refs
only.
pub unsafe fn from_owned_ptr<T>(self, ptr: *mut PyObject) -> &'py Twhere
T: FromPyPointer<'py>,
Py::from_owned_ptr(py, ptr)
or Bound::from_owned_ptr(py, ptr)
insteadgil-refs
only.Registers the object pointer in the release pool, and does an unchecked downcast to the specific type.
§Safety
Callers must ensure that ensure that the cast is valid.
sourcepub unsafe fn from_owned_ptr_or_err<T>(
self,
ptr: *mut PyObject,
) -> PyResult<&'py T>where
T: FromPyPointer<'py>,
👎Deprecated since 0.21.0: use Py::from_owned_ptr_or_err(py, ptr)
or Bound::from_owned_ptr_or_err(py, ptr)
insteadAvailable on crate feature gil-refs
only.
pub unsafe fn from_owned_ptr_or_err<T>(
self,
ptr: *mut PyObject,
) -> PyResult<&'py T>where
T: FromPyPointer<'py>,
Py::from_owned_ptr_or_err(py, ptr)
or Bound::from_owned_ptr_or_err(py, ptr)
insteadgil-refs
only.Registers the owned object pointer in the release pool.
Returns Err(PyErr)
if the pointer is NULL.
Does an unchecked downcast to the specific type.
§Safety
Callers must ensure that ensure that the cast is valid.
sourcepub unsafe fn from_owned_ptr_or_opt<T>(
self,
ptr: *mut PyObject,
) -> Option<&'py T>where
T: FromPyPointer<'py>,
👎Deprecated since 0.21.0: use Py::from_owned_ptr_or_opt(py, ptr)
or Bound::from_owned_ptr_or_opt(py, ptr)
insteadAvailable on crate feature gil-refs
only.
pub unsafe fn from_owned_ptr_or_opt<T>(
self,
ptr: *mut PyObject,
) -> Option<&'py T>where
T: FromPyPointer<'py>,
Py::from_owned_ptr_or_opt(py, ptr)
or Bound::from_owned_ptr_or_opt(py, ptr)
insteadgil-refs
only.Registers the owned object pointer in release pool.
Returns None
if the pointer is NULL.
Does an unchecked downcast to the specific type.
§Safety
Callers must ensure that ensure that the cast is valid.
sourcepub unsafe fn from_borrowed_ptr<T>(self, ptr: *mut PyObject) -> &'py Twhere
T: FromPyPointer<'py>,
👎Deprecated since 0.21.0: use Py::from_borrowed_ptr(py, ptr)
or Bound::from_borrowed_ptr(py, ptr)
insteadAvailable on crate feature gil-refs
only.
pub unsafe fn from_borrowed_ptr<T>(self, ptr: *mut PyObject) -> &'py Twhere
T: FromPyPointer<'py>,
Py::from_borrowed_ptr(py, ptr)
or Bound::from_borrowed_ptr(py, ptr)
insteadgil-refs
only.Does an unchecked downcast to the specific type.
Panics if the pointer is NULL.
§Safety
Callers must ensure that ensure that the cast is valid.
sourcepub unsafe fn from_borrowed_ptr_or_err<T>(
self,
ptr: *mut PyObject,
) -> PyResult<&'py T>where
T: FromPyPointer<'py>,
👎Deprecated since 0.21.0: use Py::from_borrowed_ptr_or_err(py, ptr)
or Bound::from_borrowed_ptr_or_err(py, ptr)
insteadAvailable on crate feature gil-refs
only.
pub unsafe fn from_borrowed_ptr_or_err<T>(
self,
ptr: *mut PyObject,
) -> PyResult<&'py T>where
T: FromPyPointer<'py>,
Py::from_borrowed_ptr_or_err(py, ptr)
or Bound::from_borrowed_ptr_or_err(py, ptr)
insteadgil-refs
only.Does an unchecked downcast to the specific type.
Returns Err(PyErr)
if the pointer is NULL.
§Safety
Callers must ensure that ensure that the cast is valid.
sourcepub unsafe fn from_borrowed_ptr_or_opt<T>(
self,
ptr: *mut PyObject,
) -> Option<&'py T>where
T: FromPyPointer<'py>,
👎Deprecated since 0.21.0: use Py::from_borrowed_ptr_or_opt(py, ptr)
or Bound::from_borrowed_ptr_or_opt(py, ptr)
insteadAvailable on crate feature gil-refs
only.
pub unsafe fn from_borrowed_ptr_or_opt<T>(
self,
ptr: *mut PyObject,
) -> Option<&'py T>where
T: FromPyPointer<'py>,
Py::from_borrowed_ptr_or_opt(py, ptr)
or Bound::from_borrowed_ptr_or_opt(py, ptr)
insteadgil-refs
only.Does an unchecked downcast to the specific type.
Returns None
if the pointer is NULL.
§Safety
Callers must ensure that ensure that the cast is valid.
sourcepub fn check_signals(self) -> PyResult<()>
pub fn check_signals(self) -> PyResult<()>
Lets the Python interpreter check and handle any pending signals. This will invoke the corresponding signal handlers registered in Python (if any).
Returns Err(
PyErr
)
if any signal handler raises an exception.
These signals include SIGINT
(normally raised by CTRL + C), which by default raises
KeyboardInterrupt
. For this reason it is good practice to call this function regularly
as part of long-running Rust functions so that users can cancel it.
§Example
use pyo3::prelude::*;
#[pyfunction]
fn loop_forever(py: Python<'_>) -> PyResult<()> {
loop {
// As this loop is infinite it should check for signals every once in a while.
// Using `?` causes any `PyErr` (potentially containing `KeyboardInterrupt`)
// to break out of the loop.
py.check_signals()?;
// do work here
}
}
§Note
This function calls PyErr_CheckSignals()
which in turn may call signal handlers.
As Python’s signal
API allows users to define custom signal handlers, calling this
function allows arbitrary Python code inside signal handlers to run.
If the function is called from a non-main thread, or under a non-main Python interpreter,
it does nothing yet still returns Ok(())
.
sourcepub unsafe fn new_pool(self) -> GILPool
👎Deprecated since 0.21.0: code not using the GIL Refs API can safely remove use of Python::new_pool
Available on crate feature gil-refs
only.
pub unsafe fn new_pool(self) -> GILPool
Python::new_pool
gil-refs
only.Create a new pool for managing PyO3’s GIL Refs. This has no functional use for code which does not use the deprecated GIL Refs API.
When this GILPool
is dropped, all GIL Refs created after this GILPool
will
all have their Python reference counts decremented, potentially allowing Python to drop
the corresponding Python objects.
Typical usage of PyO3 will not need this API, as Python::with_gil
automatically creates
a GILPool
where appropriate.
Advanced uses of PyO3 which perform long-running tasks which never free the GIL may need to use this API to clear memory, as PyO3 usually does not clear memory until the GIL is released.
§Examples
Python::with_gil(|py| {
// Some long-running process like a webserver, which never releases the GIL.
loop {
// Create a new pool, so that PyO3 can clear memory at the end of the loop.
#[allow(deprecated)] // `new_pool` is not needed in code not using the GIL Refs API
let pool = unsafe { py.new_pool() };
// It is recommended to *always* immediately set py to the pool's Python, to help
// avoid creating references with invalid lifetimes.
let py = pool.python();
// do stuff...
}
});
§Safety
Extreme care must be taken when using this API, as misuse can lead to accessing invalid
memory. In addition, the caller is responsible for guaranteeing that the GIL remains held
for the entire lifetime of the returned GILPool
.
Two best practices are required when using this API:
- From the moment
new_pool()
is called, only thePython
token from the returnedGILPool
(accessible using.python()
) should be used in PyO3 APIs. All other olderPython
tokens with longer lifetimes are unsafe to use until theGILPool
is dropped, because they can be used to create PyO3 owned references which have lifetimes which outlive theGILPool
. - Similarly, methods on existing owned references will implicitly refer back to the
Python
token which that reference was originally created with. If the returned values from these methods are owned references they will inherit the same lifetime. As a result, Rust’s lifetime rules may allow them to outlive theGILPool
, even though this is not safe for reasons discussed above. Care must be taken to never access these return values after theGILPool
is dropped, unless they are converted toPy<T>
before the pool is dropped.
source§impl Python<'_>
impl Python<'_>
sourcepub fn with_pool<F, R>(&self, f: F) -> R
👎Deprecated since 0.21.0: code not using the GIL Refs API can safely remove use of Python::with_pool
Available on crate feature gil-refs
only.
pub fn with_pool<F, R>(&self, f: F) -> R
Python::with_pool
gil-refs
only.Creates a scope using a new pool for managing PyO3’s GIL Refs. This has no functional use for code which does not use the deprecated GIL Refs API.
This is a safe alterantive to new_pool
as
it limits the closure to using the new GIL token at the cost of
being unable to capture existing GIL-bound references.
Note that on stable Rust, this API suffers from the same the SendWrapper
loophole
as allow_threads
, c.f. the documentation of the Ungil
trait,
§Examples
Python::with_gil(|py| {
// Some long-running process like a webserver, which never releases the GIL.
loop {
// Create a new scope, so that PyO3 can clear memory at the end of the loop.
#[allow(deprecated)] // `with_pool` is not needed in code not using the GIL Refs API
py.with_pool(|py| {
// do stuff...
});
}
});
The Ungil
bound on the closure does prevent hanging on to existing GIL-bound references
Python::with_gil(|py| {
let old_str = PyString::new(py, "a message from the past");
py.with_pool(|_py| {
print!("{:?}", old_str);
});
});
or continuing to use the old GIL token
Python::with_gil(|old_py| {
old_py.with_pool(|_new_py| {
let _none = old_py.None();
});
});
source§impl<'unbound> Python<'unbound>
impl<'unbound> Python<'unbound>
sourcepub unsafe fn assume_gil_acquired() -> Python<'unbound>
pub unsafe fn assume_gil_acquired() -> Python<'unbound>
Unsafely creates a Python token with an unbounded lifetime.
Many of PyO3 APIs use Python<'_>
as proof that the GIL is held, but this function can be
used to call them unsafely.
§Safety
- This token and any borrowed Python references derived from it can only be safely used whilst the currently executing thread is actually holding the GIL.
- This function creates a token with an unbounded lifetime. Safe code can assume that
holding a
Python<'py>
token means the GIL is and stays acquired for the lifetime'py
. If you let it or borrowed Python references escape to safe code you are responsible for bounding the lifetime'unbound
appropriately. For more on unbounded lifetimes, see the nomicon.
Trait Implementations§
Auto Trait Implementations§
impl<'py> Freeze for Python<'py>
impl<'py> RefUnwindSafe for Python<'py>
impl<'py> !Send for Python<'py>
impl<'py> !Sync for Python<'py>
impl<'py> Unpin for Python<'py>
impl<'py> UnwindSafe for Python<'py>
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit
)source§impl<T> IntoEither for T
impl<T> IntoEither for T
source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moresource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more