Rust bindings for Python, including tools for creating native Python extension modules. Running and interacting with Python code from a Rust binary is also supported.
PyO3 supports the following software versions: - Python 3.6 and up (CPython and PyPy) - Rust 1.41 and up
You can use PyO3 to write a native Python module in Rust, or to embed Python in a Rust binary. The following sections explain each of these in turn.
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
```toml [package] name = "string-sum" version = "0.1.0" edition = "2018"
[lib] name = "string_sum"
#
bin/
, examples/
, and tests/
) will not be ableuse string_sum;
unless the "rlib" or "lib" crate type is also included, e.g.:crate-type = ["cdylib"]
[dependencies.pyo3] version = "0.14.4" features = ["extension-module"] ```
src/lib.rs
```rust use pyo3::prelude::*;
/// Formats the sum of two numbers as string.
fn sumasstring(a: usize, b: usize) -> PyResult
/// A Python module implemented in Rust. The name of this function must match
/// the lib.name
setting in the Cargo.toml
, else Python will not be able to
/// import the module.
fn stringsum(py: Python, m: &PyModule) -> PyResult<()> { m.addfunction(wrappyfunction!(sumasstring, 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:
bash
$ cd string_sum
$ python -m venv .env
$ source .env/bin/activate
$ pip install maturin
Now build and execute the module:
```bash $ maturin develop
$ python
import stringsum stringsum.sumasstring(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.
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:
bash
sudo apt install python3-dev
Start a new project with cargo new
and add pyo3
to the Cargo.toml
like this:
toml
[dependencies.pyo3]
version = "0.14.4"
features = ["auto-initialize"]
Example program displaying the value of sys.version
and the current user name:
```rust 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.
built
crate as a PyDict
Everyone is welcomed to contribute to PyO3! There are many ways to support the project, such as:
Our contributing notes and architecture guide have more resources if you wish to volunteer time for PyO3 and are searching where to start.
If you don't have time to contribute yourself but still wish to support the project's future success, some of our maintainers have Github sponsorship pages:
PyO3 is licensed under the Apache-2.0 license. Python is licensed under the Python License.