How to use Rust with Python, and how to use Python with Rust

thumbnail

Shanghai one-stop IT outsourcing service, Shanghai Co., Ltd. has been focusing on the IT field for many years, and is committed to IT outsourcing, IT operation and maintenance, network maintenance, system integration and other IT outsourcing services. Many well-known companies and listed companies have provided IT technical services. Welcome to inquire, we will serve you wholeheartedly...

Portishead1/Getty Images

Python and Rust seem to occupy opposite ends of the language spectrum. Python interpreted at runtime provides developers with a flexible and comfortable programming environment, but at the cost of raw speed. Rust offers speed and memory safety guarantees, but requires you to learn a new paradigm for handling memory operations.

In theory, these languages ​​should not compete. They should cooperate. In practice, they can. Rust can benefit from Python's ease of use, and Python can benefit from Rust's speed and safety.

If you want to use Rust with Python or Python with Rust, you need to be familiar with at least both languages ​​for best results. You also need to decide which of these two languages ​​is your primary language, as the options for each method are quite different.

Calling Rust from Python with PyO3

If Python is your primary language, integrating with Rust is conceptually the same as integrating Python with C. The default implementation of Python written in C uses extensions written in C or using a C-compatible ABI. Extensions written in Rust that use the same ABI will also work, although this is not automatic - you must use crates that specifically provide bindings for Rust functions to the Python C API.

Create Rust bindings in Python

The most widely recognized project for creating Rust bindings in Python is PyO3. It can be used to write Python modules in Rust, or to embed the Python runtime into Rust binaries.

PyO3 leverages another project, Maturin, a tool for authoring Rust crates using Python packaging and bindings. When installed in a Python virtual environment, Maturin can be used from the command line to initialize a new Rust project with Python bindings enabled. Developers use directives in Rust code to indicate which Rust functions to expose to Python, and how to expose an entire Rust project to Python as an importable module.

Mapping Rust and Python types

One of the useful aspects of PyO3 is its mapping between Rust and Python types. Functions written in Rust can accept native Python types or Rust types converted from Python types. For example, a bytearray or bytes object in Python can be elegantly mapped to a Vec<u8> in Rust, and str in Python can be rendered as a Rust string.

Converting from Python to Rust incurs a per-call cost, but it saves you from having to use Python types entirely in your Rust code. In the Cython world, this is similar to converting to a C type: each conversion has a cost, but if your goal is to do numerical processing entirely in C, they provide a significant speedup.

Call Python from Rust using the cpython crate

If you're primarily a Rust developer but want to use Python in your Rust applications, the cpython crate is a straightforward approach. The cpython crate provides Rust bindings for the CPython interpreter, the most common Python runtime (so named because it's written in C).

Rust programs can call into and use the CPython interpreter, allowing you to create and manipulate Python objects and make library calls in Rust. An example in the documentation shows how to initialize the Python runtime, import modules, create Python objects, and perform method calls.

The cpython crate also includes some useful macros. py_fn! For example, a macro wraps a Rust function so that it can be called from Python. py_class! Macros allow you to generate Rust classes as Python class objects.

If you're more familiar with Rust than Python, it's a good idea to at least be familiar with the Python C API and various Python object types before diving in.

Performance Tips

An important caveat with cpython and PyO3 is to always try to minimize the number of times data is passed back and forth between the two languages. Every call from Python to Rust (and vice versa) incurs some overhead. If the overhead outweighs the work you're doing in Rust, you won't see any significant performance improvement.

For example, if you're looping over a collection of objects, send the objects to Rust and execute the loop there. This is more efficient than looping on the Python side and calling Rust code on each iteration of the loop.

This guide also generally applies to integration between Python and other code that uses the Python C ABI, such as Cython modules.

"The talent war has changed dramatically," said Alex Kraus, vice president of consulting firm Metis Strategy. "The talent pool is much larger, sometimes global, and previously limited to where the company's headquarters were located."

Shanghai Xiniaruo has been focusing on one-stop IT outsourcing business, IT system integration services, and IT operation and maintenance management services for decades.

Latest Programming News and Information | GeekBar

Related Posts