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: Changes Python::with_gil and Python::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’s HashMap and HashSet types.
  • multiple-pymethods: Enables the use of multiple #[pymethods] blocks per #[pyclass]. This adds a dependency on the inventory crate, which is not supported on all platforms.
  • num-bigint: Enables conversions between Python objects and num-bigint’s BigInt and BigUint types.
  • num-complex: Enables conversions between Python objects and num-complex’s Complex type.
  • serde: Allows implementing serde’s Serialize and Deserialize traits for Py<T> for all T that implement Serialize and Deserialize.

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 the abi3 feature flag is enabled.
  • PyPy - Marks code enabled when compiling for PyPy.

Minimum supported Rust and Python versions

PyO3 supports Python 3.6+ and Rust 1.41+.

Building with PyPy is also possible (via cpyext) for Python 3.6, targeted PyPy version is 7.3+. Please refer to the pypy section in the guide for more information.

Example: Building a native Python module

To build, test and publish your crate as a Python module, it is recommended that you use maturin or setuptools-rust. You can also do this manually. See the Building and Distribution chapter of the guide for more information.

Add these files to your crate’s root:

Cargo.toml

[package]
name = "string-sum"
version = "0.1.0"
edition = "2018"

[lib]
name = "string_sum"
# "cdylib" is necessary to produce a shared library for Python to import from.
#
# Downstream Rust code (including code in `bin/`, `examples/`, and `tests/`) will not be able
# to `use string_sum;` unless the "rlib" or "lib" crate type is also included, e.g.:
# crate-type = ["cdylib", "rlib"]
crate-type = ["cdylib"]

[dependencies.pyo3]
version = "0.14.0"
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(())
}

.cargo/config.toml

# These flags must be passed to rustc when compiling for macOS
# They can be omitted if you pass the flags yourself
# or don't care about macOS

[target.x86_64-apple-darwin]
rustflags = [
  "-C", "link-arg=-undefined",
  "-C", "link-arg=dynamic_lookup",
]

[target.aarch64-apple-darwin]
rustflags = [
  "-C", "link-arg=-undefined",
  "-C", "link-arg=dynamic_lookup",
]

Example: Using Python from Rust

You can use PyO3 to call Python functions from Rust.

Add pyo3 to your Cargo.toml:

[dependencies.pyo3]
version = "0.14.0"
# this is necessary to automatically initialize the Python interpreter
features = ["auto-initialize"]

Example program displaying the value of sys.version:

use pyo3::prelude::*;
use pyo3::types::IntoPyDict;

fn main() -> PyResult<()> {
    let gil = Python::acquire_gil();
    let py = gil.python();
    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(())
}

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;
pub use inventory;

Modules

bufferNon-Py_LIMITED_API

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.

marshalNon-Py_LIMITED_API

Support for the Python marshal format. Not supported in limited API builds.

num_bigintnum-bigint and neither Py_LIMITED_API nor PyPy

Conversions to and from num-bigint’s BigInt and BigUint types.

num_complexnum-complex

Conversions to and from num-complexComplex<f32> and Complex<f64>.

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 our proc-macro codes.

serdeserde

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 Python object of known type T.

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.

Type Definitions

A commonly-used alias for Py<PyAny>.

Represents the result of a Python call.