Crate pyo3[−][src]
Expand description
Rust bindings to the Python interpreter.
PyO3 can be used to write native Python modules or run Python code and modules from Rust.
See the guide for a detailed introduction.
PyO3’s object types
PyO3 has several core types that you should familiarize yourself with:
The Python<’py> object
Holding the global interpreter lock
(GIL) is modeled with the Python<'py>
token.
All APIs that require that the GIL is held require this token as proof
that you really are holding the GIL. It can be explicitly acquired and
is also implicitly acquired by PyO3 as it wraps Rust functions and structs
into Python functions and objects.
The GIL-dependent types
For example &
PyAny
.
These are only ever seen as references, with a lifetime that is only valid for as long
as the GIL is held, which is why using them doesn’t require a Python<'py>
token.
The underlying Python object, if mutable, can be mutated through any reference.
See the guide for an explanation of the different Python object types.
The GIL-independent types
When wrapped in Py
<...>
, like with Py
<
PyAny
>
or Py
<SomePyClass>
, Python objects
no longer have a limited lifetime which makes them easier to store in structs and pass between functions.
However, you cannot do much with them without a
Python<'py>
token, for which you’d need to reacquire the GIL.
PyErr
The vast majority of operations in this library will return PyResult<...>
.
This is an alias for the type Result<..., PyErr>
.
A PyErr
represents a Python exception. A PyErr
returned to Python code will be raised as a Python exception.
Errors from PyO3
itself are also exposed as Python exceptions.
Feature flags
PyO3 uses feature flags to enable you to opt-in to additional functionality. For a detailed description, see the Features Reference chapter of the guide.
Default feature flags
The following features are turned on by default:
macros
: Enables various macros, including all the attribute macros.
Optional feature flags
The following features are optional:
abi3
: Restricts PyO3’s API to a subset of the full Python API which is guaranteed by PEP 384 to be forward-compatible with future Python versions.auto-initialize
: ChangesPython::with_gil
andPython::acquire_gil
to automatically initialize the Python interpreter if needed.extension-module
: This will tell the linker to keep the Python symbols unresolved, so that your module can also be used with statically linked Python interpreters. Use this feature when building an extension module.hashbrown
: Enables conversions between Python objects and hashbrown’sHashMap
andHashSet
types.indexmap
: Enables conversions between Python dictionary and indexmap’sIndexMap
.multiple-pymethods
: Enables the use of multiple#[pymethods]
blocks per#[pyclass]
. This adds a dependency on theinventory
crate, which is not supported on all platforms.num-bigint
: Enables conversions between Python objects and num-bigint’sBigInt
andBigUint
types.num-complex
: Enables conversions between Python objects and num-complex’sComplex
type.serde
: Allows implementing serde’sSerialize
andDeserialize
traits forPy
<T>
for allT
that implementSerialize
andDeserialize
.
Unstable features
nightly
: Gates some optimizations that rely on#![feature(specialization)]
, for which you’d also need nightly Rust. You should not use this feature.
rustc
environment flags
PyO3 uses rustc
’s --cfg
flags to enable or disable code used for different Python versions.
If you want to do this for your own crate, you can do so with the pyo3-build-config
crate.
Py_3_6
,Py_3_7
,Py_3_8
,Py_3_9
,Py_3_10
: Marks code that is only enabled when compiling for a given minimum Python version.Py_LIMITED_API
: Marks code enabled when theabi3
feature flag is enabled.PyPy
- Marks code enabled when compiling for PyPy.
Minimum supported Rust and Python versions
PyO3 supports the following software versions:
- Python 3.6 and up (CPython and PyPy)
- Rust 1.41 and up
Example: Building a native Python module
PyO3 can be used to generate a native Python module. The easiest way to try this out for the
first time is to use maturin
. maturin
is a tool for
building and publishing Rust-based Python packages with minimal configuration. The following
steps set up some files for an example Python module, install maturin
, and then show how build
and import the Python module.
First, create a new folder (let’s call it string_sum
) containing the following two files:
Cargo.toml
[package] name = "string-sum" version = "0.1.0" edition = "2018" [lib] name = "string_sum" crate-type = ["cdylib"] [dependencies.pyo3] version = "*" features = ["extension-module"]
src/lib.rs
use pyo3::prelude::*; /// Formats the sum of two numbers as string. #[pyfunction] fn sum_as_string(a: usize, b: usize) -> PyResult<String> { Ok((a + b).to_string()) } /// A Python module implemented in Rust. #[pymodule] fn string_sum(py: Python, m: &PyModule) -> PyResult<()> { m.add_function(wrap_pyfunction!(sum_as_string, m)?)?; Ok(()) }
With those two files in place, now maturin
needs to be installed. This can be done using
Python’s package manager pip
. First, load up a new Python virtualenv
, and install maturin
into it:
$ cd string_sum $ python -m venv .env $ source .env/bin/activate $ pip install maturin
Now build and execute the module:
$ maturin develop $ python >>> import string_sum >>> string_sum.sum_as_string(5, 20) '25'
As well as with maturin
, it is possible to build using
setuptools-rust
or
manually. Both offer more
flexibility than maturin
but require further configuration.
Example: Using Python from Rust
To embed Python into a Rust binary, you need to ensure that your Python installation contains a shared library. The following steps demonstrate how to ensure this (for Ubuntu), and then give some example code which runs an embedded Python interpreter.
To install the Python shared library on Ubuntu:
sudo apt install python3-dev
Start a new project with cargo new
and add pyo3
to the Cargo.toml
like this:
[dependencies.pyo3] version = "*" features = ["auto-initialize"]
Example program displaying the value of sys.version
and the current user name:
use pyo3::prelude::*; use pyo3::types::IntoPyDict; fn main() -> PyResult<()> { Python::with_gil(|py| { let sys = py.import("sys")?; let version: String = sys.get("version")?.extract()?; let locals = [("os", py.import("os")?)].into_py_dict(py); let code = "os.getenv('USER') or os.getenv('USERNAME') or 'Unknown'"; let user: String = py.eval(code, None, Some(&locals))?.extract()?; println!("Hello {}, I'm Python {}", user, version); Ok(()) }) }
The guide has a section with lots of examples about this topic.
Other Examples
The PyO3 README contains quick-start examples for both using Rust from Python and Python from Rust.
The PyO3 repository’s examples subdirectory contains some basic packages to demonstrate usage of PyO3.
There are many projects using PyO3 - see a list of some at https://github.com/PyO3/pyo3#examples
Re-exports
pub use crate::class::*;
pub use crate::conversion::AsPyPointer;
pub use crate::conversion::FromPyObject;
pub use crate::conversion::FromPyPointer;
pub use crate::conversion::IntoPy;
pub use crate::conversion::IntoPyPointer;
pub use crate::conversion::PyTryFrom;
pub use crate::conversion::PyTryInto;
pub use crate::conversion::ToBorrowedObject;
pub use crate::conversion::ToPyObject;
pub use crate::pycell::PyCell;
pub use crate::pycell::PyRef;
pub use crate::pycell::PyRefMut;
pub use crate::pyclass::PyClass;
pub use crate::pyclass_init::PyClassInitializer;
pub use crate::type_object::PyTypeInfo;
Modules
PyBuffer
implementation
Python object protocols
Conversions between various states of Rust and Python types and their wrappers.
Exception types defined by Python.
Raw FFI declarations for Python’s C API.
Internals of PyO3 which are accessed by code expanded from PyO3’s procedural macros. Usage of any of these APIs in downstream code is implicitly acknowledging that these APIs may change at any time without documentation in the CHANGELOG and without breaking semver guarantees.
Support for the Python marshal
format. Not supported in limited API
builds.
A write-once cell mediated by the Python GIL.
Helper to convert Rust panics to Python exceptions.
A collection of items you most likely want to have in scope when working with pyo3
The proc macros, all of which are part of the prelude.
Includes PyCell
implementation.
PyClass
and related traits.
Initialization utilities for #[pyclass]
.
This module contains additional fields for #[pyclass]
.
Mainly used by PyO3’s proc-macro code.
Python type object information
Various types defined by the Python interpreter such as int
, str
and tuple
.
Macros
Defines a new exception type.
impl $crate::type_object::PyTypeObject for $name
where $name
is an
exception newly defined in Rust code.
The boilerplate to convert between a Rust type and a Python exception.
Defines a Rust type for an exception defined in Python code.
A convenient macro to execute a Python code snippet, with some local variables set.
Declares all of the boilerplate for Python types which can be inherited from (because the exact Python layout is known).
Declares all of the boilerplate for Python types.
Returns a function that takes a Python instance and returns a Python function.
Returns a function that takes a Python instance and returns a Python module.
Structs
RAII type that represents the Global Interpreter Lock acquisition.
A RAII pool which PyO3 uses to store owned Python references.
A GIL-independent reference to an object allocated on the Python heap.
Represents any Python object.
Error that indicates a failure to convert a PyAny to a more specific Python type.
Represents a Python exception that was raised.
Marker type that indicates that the GIL is currently held.
Represents the major, minor, and patch (if any) versions of this interpreter.
Traits
Helper conversion trait that allows to use custom arguments for lazy exception construction.
Types that are built into the Python interpreter.
Functions
Prepares the use of Python in a free-threaded context.
Executes the provided closure with an embedded Python interpreter.