DEV Community


Posted on

Talking to python with rust

A few words about Rust

Rust is a systems programming language that runs blazingly fast, prevents segfaults, and guarantees thread safety.

Why write Python modules in Rust?

Python is undoubtedly one of the more powerful programming languages, but there are situations when a faster and more low-level tool is required. For example, calculations in which we care about the fastest possible code execution

Getting started

1. Install Rust and Cargo

On Linux and macOS systems, this is done as follows:

$ curl -sSf | sh
Enter fullscreen mode Exit fullscreen mode

On Windows, download and run rustup-init.exe. It will start the installation in a console and present the above message on success.

2. Create new project and edit Cargo.toml

$ cargo new pyrustlib --lib
Enter fullscreen mode Exit fullscreen mode

To your Cargo.toml file you should add cpython dependency, this file should looks like

name = "pyrustlib"
version = "0.1.0"
edition = "2021"

name = "pyrust"
crate-type = ["dylib"]

version = "0.7"
features = ["extension-module"]
Enter fullscreen mode Exit fullscreen mode

Let's talk to Python

Next, we’re going to open src/ and begin editing; this is where the actual code of our library lives.

extern crate cpython;

use cpython::{Python, PyResult, PyString};

fn hello_from_rust(_py: Python) -> PyResult<PyString> {
    Ok(PyString::new(_py, "Hello from Rust!"))

py_module_initializer!(libpyrust, libpyrust, PyInit_libpyrust, |py, m | {
    m.add(py, "__doc__", "This module is implemented in Rust")?;
    m.add(py, "hello_world", py_fn!(py, hello_from_rust()))?;
Enter fullscreen mode Exit fullscreen mode

py_module_initializer is a macro defined by the cpython crate we imported at the top of our library. The first parameter (‘status’) is the name of our module, the second parameter is the Python2 naming for our module, while the third parameter is for Python3. The last segment of code on the first line (py, m) allows the modification of received module objects.

We then add a docstring and use the py_fn! macro to build the Python version of our function. That’s all there is to it! Save and exit.

Compile the code

Make sure you are in the root directory of the project (where the Cargo.toml file is).
Run the following command to compile the code:

cargo build --release 
Enter fullscreen mode Exit fullscreen mode

If the compilation went successfully you will see a new target directory in the main project directory. You can find the library in target/release, it's named

Test in python interpreter

The name for import this module in python is name given in py_module_initializer which in my case is libpyrust

Image description

As you can see, our module works properly.

Additional Information

For more advanced usage of cpython I recommend looking through the rust-cpython repo


I really hope you found this tutorial helpful in some way! If you notice any errors or inaccuracies, please drop me a message. I want to invite you to my github, maybe you found something interesting. Thanks for reading!

Top comments (1)

one_past_last_jedi profile image
One Past Last Jedi

Nice ☺🙂