Rust bindings for the Python interpreter
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.

README.md

PyO3

Build Status Build Status codecov crates.io Join the dev chat

Rust bindings for Python. This includes running and interacting with python code from a rust binaries as well as writing native python modules.

A comparison with rust-cpython can be found in the guide.

Usage

Pyo3 supports python 2.7 as well as python 3.5 and up. The minimum required rust version is 1.30.0-nightly 2018-08-18.

You can either write a native python module in rust or use python from a rust binary.

Using rust from python

Pyo3 can be used to generate a native python module.

Cargo.toml:

[package]
name = "rust-py"
version = "0.1.0"

[lib]
name = "rust_py"
crate-type = ["cdylib"]

[dependencies.pyo3]
version = "0.4"
features = ["extension-module"]

src/lib.rs

#![feature(specialization)]

#[macro_use]
extern crate pyo3;

use pyo3::prelude::*;

#[pyfunction]
/// Formats the sum of two numbers as string
fn sum_as_string(a: usize, b: usize) -> PyResult<String> {
    Ok((a + b).to_string())
}

/// This module is a python moudle implemented in Rust.
#[pymodinit]
fn rust_py(py: Python, m: &PyModule) -> PyResult<()> {
    m.add_function(wrap_function!(sum_as_string))?;

    Ok(())
}

On windows and linux, you can build normally with cargo build --release. On Mac Os, you need to set additional linker arguments. One option is to compile with cargo rustc --release -- -C link-arg=-undefined -C link-arg=dynamic_lookup, the other is to create a .cargo/config with the following content:

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

Also on macOS, you will need to rename the output from *.dylib to *.so. On Windows, you will need to rename the output from *.dll to *.pyd.

setuptools-rust can be used to generate a python package and includes the commands above by default. See examples/word-count and the associated setup.py.

Using python from rust

Add pyo3 this to your Cargo.toml:

[dependencies]
pyo3 = "0.3"

Example program displaying the value of sys.version:

#![feature(specialization)]

extern crate pyo3;

use pyo3::prelude::*;

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 = PyDict::new(py);
    locals.set_item("os", py.import("os")?)?;
    let user: String = py.eval("os.getenv('USER') or os.getenv('USERNAME')", None, Some(&locals))?.extract()?;

    println!("Hello {}, I'm Python {}", user, version);
    Ok(())
}

Examples and tooling

License

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