Как я Rust в Python встраивал

Ведение

Сейчас Rust "на хайпе" и вместе с этим появляются много библиотек и инструментария для Python написанные на Rust. Год назад стал появляться Ruff в моем инфополе, а до этого pydantic выпустил версию 2 с ядром на Rust. Сейчас уже есть uv, который потихоньку теснит Poetry.

На этом фоне я несколько месяцев назад увлекся этим языком. В свободное время изучаю Rust-код в проектах, которые я упоминал выше и не только. А в данной статье покажу, как создать простенькую библиотеку кодирования данных в Base 64.

Подготовка

Устанавливаем Rust

Скрипт для установки (Linux/macOS):

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

После этого у вас установятся инструментарий для работы с Rust.

Создаем проект и окружение

mkdir pyrsbase64
cd pyrsbase64

python -m venv .venv
source .venv/bin/activate

После создания окружения нам нужно будет установить утилиту для сборки Python пакетов написанных на Rust - Maturin:

pip install maturin

И с помощью него инициализировать проект:

maturin init -b pyo3

Опция -b pyo3 означает что мы будем использовать библиотеку PyO3 для создания расширения (Maturin также поддерживает создание расширений на Си).

Проект будет иметь следующую структуру:

├── Cargo.lock     # Файл заморозки Rust зависимостей
├── Cargo.toml     # Конфигурация Rust пакета
├── pyproject.toml # Конфигурация Python пакета
└── src            # Папка с Rust-кодом 
    └── lib.rs     # Главный файл пакета Rust (аналог __init__.py Python)

Файл lib.rs уже будет содержать пример кода на Rust:

use pyo3::prelude::*;

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

/// A Python module implemented in Rust.
#[pymodule]
fn pyrsbase64(m: &Bound<'_, PyModule>) -> PyResult<()> {
    m.add_function(wrap_pyfunction!(sum_as_string, m)?)?;
    Ok(())
}

Вы можете скомпилировать проект и попробовать вызвать функцию:

## Компиляция проекта и установка в окружение .venv
maturin develop

## Вызов python-скрипта
python main.py

Код main.py:

import pyrsbase64

assert '3' == pyrsbase64.sum_as_string(1, 2)

Пишем функцию на Rust

Так как мы пишем библиотеку для работы с Base 64, то давайте установим пакет для кодирования в Base 64 на Rust (написание своей реализации было бы темой для другой статьи).

cargo add base64

Это установит крейт base64. Крейт (от англ. crate - "ящик") - пакеты (библиотеки) в Rust.

Очистим lib.rs и добавим следующий код

use pyo3::prelude::{pyfunction, PyResult};
use base64::engine::general_purpose::STANDARD as base64_standard;

#[pyfunction]
fn b64encode(s: &[u8]) -> PyResult<String> {
	return Ok(base64_standard.encode(s))
}

Разбор

Здесь можно сказать, что мы просто написали "прокси"-функцию, которая вызывает функцию из другого пакета Rust.

Добавим определение Python-модуля

Для того, чтобы экспортировать функцию из Rust-пакета, которую мы написали ранее, нам нужно будет определить наш модуль и добавить нашу функцию в нее.

При инициализации проекта Maturin позаботился и создал определение нашего модуля в lib.rs. Немного видоизменим его

use pyo3::prelude::pymodule;

#[pymodule]
fn pyrsbase64(m: &Bound<'_, PyModule>) -> PyResult<()>; {
    m.add_function(wrap_pyfunction!(b64encode, m)?)?;
    Ok(())
}

Собираем проект

На этом наша простая библиотека кодирования в Base 64 готова к использованию в Python. Можем собрать наш проект и попробовать вызывать ее.

Измените main.py

import pyrsbase64

assert "SGVsbG8sIFdvcmxkIQ==" == pyrsbase64.b64encode(b"Hello, World!")

Запускаем скрипт

maturin develop && python main.py

Заключение

Потихоньку многие open-source проекты на Си будут переписываться на Rust, а экосистема Rust в Python будет еще стремительней развиваться. Вскоре Rust войдет в CPython, как язык для встроенных в стандартную библиотеку расширений (см. Pre-PEP). Я надеюсь, что это статья вас увлечет в этой теме и вы будете создавать свои расширения для Python на Rust.

Ресурсы

@baaaqt
27.11.2025 12:14 UTC
Первоисточник

Комментарии

@Nuflyn
27.11.2025 07:42 UTC
+1

Связка maturin с PyO3 очень хорошо сделана. И они на очень зрелой стадии разработки и бойлерплейта с обеих сторон не сильно много получается и консольного шаманства.

@Sega100500
01.12.2025 14:37 UTC
-1

Для начала я бы посоветовал (скромно) автору всё же получше изучить Rust (если это вообще в принципе возможно для питониста (в чём я, честно говоря, сомневаюсь)). Даже в столь простом примере вы умудрились сделать ошибки - сравните хотя бы свой пример с тем же самым, но на странице библиотеки PyO3, о которой вы сами говорите.
Я далеко не сторонник "питуха", а скорее даже наоборот, поэтому я думаю, что сама по себе эта идея, мягко выражаясь, не очень - изобретать на Rust очередные костыли для python.

@baaaqt
01.12.2025 17:07 UTC
0

Спасибо за обратную связь! Я внимательно проверил пример и не вижу ошибок. Цель примера - показать рабочий подход интеграции Rust с Python.

@server41k
03.07.2026 14:46 UTC
0

уровень снобизма - пользователь хабра

03.07.2026 15:12 UTC
0

да уж куда мне до авторства статей, конечно - всего лишь обычный пользователь хабра