PR

【Python×Rust】uvとMaturinで構築する高速ハイブリッド開発環境!Ubuntu対応版 🦀🐍

「Pythonの書きやすさは最高だけど、特定の処理だけもっと高速化したい…」
「Rustで高速なロジックを書いて、Pythonから手軽に呼び出せるって本当?」
「uvとMaturinを組み合わせた今どきのハイブリッド開発環境、どうやって作るの?」

こんにちは! Pythonプログラミング探検隊、隊長のPythonistaです! 前回のシリーズでは地理計算の自動化や地図の可視化を学び、Pythonの便利さを改めて実感しましたね。

今回はプログラミングのさらなる深淵、「Python×Rustのハイブリッド開発」の世界へ飛び込みます!Pythonの「圧倒的な開発スピード」と、Rustの「圧倒的な実行速度」をいいとこ取りする環境を、次世代の高速パッケージマネージャーuvと、Python・Rustの架け橋となるツールMaturin (PyO3)を使って構築します。

今回は、Ubuntu環境をベースに、私が実際に環境を構築する中で直面した「超重要な名前のルール」やトラブルシューティングも含めて、次回の自分へのメモとしても役立つ完全リファレンスとしてまとめました。さあ、2つの強力な言語を融合させましょう!


1. 開発環境の初期構築(最初の一回のみ)

まずは、JetPack環境にRustのコンパイラを導入し、uvから正しく参照できるようにベースを整えます。以下のコマンドをターミナルで実行しましょう。

# 1. Rust公式インストーラーの実行 (選択肢が表示されたら「1」を選択)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# 2. 現在のシェルに環境変数を反映
source $HOME/.cargo/env

✅ インストールの確認方法

正しくインストールできたか、バージョンコマンドで確認します。

rustc --version
cargo --version

ここで rustc 1.x.x のようにバージョン番号が表示されれば、Rust側の準備はバッチリです!


2. 新規プロジェクトの立ち上げ手順

uvには、最初からMaturin(Rustハイブリッド構成)をビルドバックエンドに指定してプロジェクトを初期化する機能が備わっています。今回はPythonとRustが同居する構成(–mixed構成)を作成します。

# 1. プロジェクトの作成(例: rust_test)と移動
uv init --build-backend maturin rust_test
cd rust_test

# 2. JetPack環境用の設定フォルダ・ファイルを作成
mkdir .cargo
nano .cargo/config.toml

新しく作成した .cargo/config.toml の中に、以下の2行を記述して保存(Ctrl+O ➔ Enter ➔ Ctrl+X)します。

[env]
PYO3_PYTHON = { value = ".venv/bin/python", relative = true, force = true }

💡 ここがポイント!:
この設定により、Rustコンパイラがuvの作成する仮想環境(.venv)内のPythonを確実に狙い撃ちしてビルドできるようになります。環境のパスの迷子を防ぐための必須の設定です。


3.【重要】ハイブリッド開発の「3つの名前」のルール

ここが、私が開発中にエラーに悩まされた最も重要なポイントです!
Rustで書いた関数をPython側からスムーズに呼び出すには、「Cargo.toml」「lib.rs」「__init__.py」の3つのファイルに登場する定義名が、パズルのように完全に一致している必要があります。

今回は、Rust側のコア処理を _core というモジュール名にして、裏側で連携させる場合の正しい設定例を見てみましょう。

① `Cargo.toml` の設定

Rustが出力するバイナリ(ライブラリ)の名前を _core に指定します。

[package]
name = "rust_test"
version = "0.1.0"
edition = "2021"

[lib]
name = "_core"          # ⚠️ 必ず Python 側が読み込む名前(_core)にする
crate-type = ["cdylib"]

[dependencies]
pyo3 = { version = "0.21", features = ["extension-module"] }

② `src/lib.rs` の設定

Rustコード側です。モジュール登録名を、上記と同じ _core にします。

use pyo3::prelude::*;

# [pyfunction] // Pythonに公開したい関数
fn hello_from_bin() -> String {
    "Hello from Rust!".to_string()
}

# [pymodule]
# ⚠️ 関数名を「_core」にし、[lib] name = "_core" と完全に一致させる!
fn _core(m: &Bound<'_, PyModule>) -> PyResult<()> {
    m.add_function(wrap_pyfunction!(hello_from_bin, m)?)?;
    Ok(())
}

③ `src/rust_test/__init__.py` の設定

Pythonパッケージの玄関口です。ここで裏側(_core)のRust関数を表のパッケージ関数として引っ張り出します。

# _core から関数をインポートして、パッケージの関数として公開する
from rust_test._core import hello_from_bin

__all__ = ["hello_from_bin"]

この3つの設定が綺麗に噛み合うことで、PythonとRustの境界線が消え、シームレスに関数の呼び出しができるようになります!


4. 既存の uv プロジェクトに Rust を後付けする方法

「すでに運用中の一般的なPythonプロジェクト(普通に uv init したもの)があるんだけど、後から一部の処理だけRust化したいな…」という場合も、一からやり直す必要はありません。以下のファイルを手動で配置・追記すれば、全く同じ環境へアップグレードできます!

  1. Cargo.toml をルート直下に新規作成する(内容は「3」の①と同じ)
  2. src/lib.rs を新規作成する(内容は「3」の②と同じ)
  3. .cargo/config.toml を新規作成する(内容は「2」と同じ)
  4. src/[パッケージ名]/__init__.py を編集する(内容は「3」の③と同じ)
  5. pyproject.toml の最下部に以下を追記する
[build-system]
requires = ["maturin>=1.0,<2.0"]
build-backend = "maturin"

[tool.maturin]
manifest-path = "Cargo.toml"
module-name = "rust_test._core" # 自身のパッケージ名に合わせて変更

5. 日常の開発フロー(コード変更と実行)

一度この環境さえ整ってしまえば、日々の開発ステップは拍子抜けするほどシンプルです!
【Rustのコード(lib.rs)を編集】➔【Pythonコード(run.py)から呼び出し】➔【uv run run.py

これだけです!

uv run run.py

💡 ここが最高に便利!:
uv run を実行すると、uvが裏側で「Rustのコードが書き換わったかどうか」を自動検知してくれます。もし変更があれば、バックグラウンドで自動的に maturin が走り、高速で自動再コンパイル(ビルド)を行った後に、そのままPythonスクリプトを実行してくれます。
開発者が手動で毎回ビルドコマンドを打つ必要は一切なく、通常のPythonスクリプトを開発しているのと全く同じテンポで、爆速のRustコードをガシガシ書いていくことができます!


6. トラブルシューティングと確認方法

万が一、ハイブリッド開発中に動かなくなってしまった場合のチェックリストです。困ったらここを確認してください。

エラー内容・現象原因対策
ImportError: dynamic module does not define...Rust側とPython側での「名前」の不一致。Cargo.toml[lib] name と、lib.rs#[pymodule] fn の名前が完全に一致しているか再確認する。
AttributeError: module '...' has no attribute '...'__init__.py での公開漏れ。
② キャッシュのバグ。
__init__.py に新しい関数を追記したか確認。
src/[パッケージ名]/_core.pyi を削除し、uv run --no-cache run.py を実行。
Maturin 関連のビルドエラー仮想環境の Python パスを Rust 側が見失っている。.cargo/config.toml が正しくルートに配置され、記述内容が間違っていないか確認。

まとめ

今回は、Ubuntu/JetPack環境において、次世代パッケージマネージャーuvMaturinを使って、Python×Rustのハイブリッド環境を構築する方法をまとめました。

一見複雑に見える多言語の連携ですが、uvの自動ビルド検知のおかげで、一度組んでしまえば非常に快適な開発ライフが送れます。Pythonの手軽さとRustの圧倒的パワーを融合させ、あなたのプログラムを次の次元へと進化させてみてください!

Happy Rust Hacking! 🦀🐍

コメント

タイトルとURLをコピーしました