PyO3

actions status benchmark codecov crates.io minimum rustc 1.41 dev chat contributing notes

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.

Usage

PyO3 supports Python 3.6 and up. The minimum required Rust version is 1.41.

PyPy is also supported. Some minor features are unavailable on PyPy - please refer to the pypy section in the guide for more information.

You can either write a native Python module in Rust, or use Python from a Rust binary.

However, on some OSs, you need some additional packages. E.g. if you are on Ubuntu 18.04, please run

bash sudo apt install python3-dev python-dev

Using Rust from Python

PyO3 can be used to generate a native Python module.

Cargo.toml

```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

```rust use pyo3::prelude::*;

/// Formats the sum of two numbers as string.

[pyfunction]

fn sumasstring(a: usize, b: usize) -> PyResult { Ok((a + b).to_string()) }

/// A Python module implemented in Rust.

[pymodule]

fn stringsum(py: Python, m: &PyModule) -> PyResult<()> { m.addfunction(wrappyfunction!(sumas_string, m)?)?;

Ok(())

} ```

While developing, you can symlink (or copy) and rename the shared library from the target folder: On MacOS, rename libstring_sum.dylib to string_sum.so, on Windows libstring_sum.dll to string_sum.pyd, and on Linux libstring_sum.so to string_sum.so. Then open a Python shell in the same folder and you'll be able to import string_sum.

To build, test and publish your crate as a Python module, you can use maturin or setuptools-rust. You can find an example for setuptools-rust in examples/word-count, while maturin should work on your crate without any configuration.

Using Python from Rust

If you want your Rust application to create a Python interpreter internally and use it to run Python code, add pyo3 to your Cargo.toml like this:

toml [dependencies.pyo3] version = "0.14.0" 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() -> Result<(), ()> { Python::withgil(|py| { main(py).maperr(|e| { // We can't display Python exceptions via std::fmt::Display, // so print the error here manually. e.printandsetsyslastvars(py); }) }) }

fn main(py: Python) -> PyResult<()> { let sys = py.import("sys")?; let version: String = sys.get("version")?.extract()?; let locals = [("os", py.import("os")?)].intopy_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(()) } ```

Our guide has a section with lots of examples about this topic.

Tools and libraries

Examples

Contributing

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:

License

PyO3 is licensed under the Apache-2.0 license. Python is licensed under the Python License.