Why not login to Qiita and try out its useful features?

We'll deliver articles that match you.

You can read useful information later.

3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

uvとPyO3でPythonからRustを呼ぶ①(プロジェクト作成・Hello World実行まで)

Last updated at Posted at 2025-01-27

はじめに

備忘用。②以降も書くかもしれない。
勉強し始めの初心者のため、何か指摘や気づきがあれば是非コメントお願いします。

→(追記)②を書きました。

実行環境

Windows 11
uv 0.5.24
python 3.12.1
rustup 1.27.1
rustc 1.79.0
cargo 1.79.0
maturin 1.5.1
pyo3 0.22.4

プロジェクト作成

参考:https://docs.astral.sh/uv/concepts/projects/init/#projects-with-extension-modules

公式docの通り、以下を実行すると、プロジェクトが作成されます。

> uv init --build-backend maturin example-ext

ディレクトリ構成は以下の通り。

> tree /f example-ext
example-ext
│  .gitignore
│  .python-version
│  Cargo.toml
│  pyproject.toml
│  README.md
│
└─src
    │  lib.rs
    │
    └─example_ext
            _core.pyi
            __init__.py

主要なファイルの内容は以下の通り。

src/lib.rs
use pyo3::prelude::*;

#[pyfunction]
fn hello_from_bin() -> String {
    "Hello from example-ext!".to_string()
}

/// A Python module implemented in Rust. The name of this function must match
/// the `lib.name` setting in the `Cargo.toml`, else Python will not be able to
/// import the module.
#[pymodule]
fn _core(m: &Bound<'_, PyModule>) -> PyResult<()> {
    m.add_function(wrap_pyfunction!(hello_from_bin, m)?)?;
    Ok(())
}
src/example_ext/__init__.py
from example_ext._core import hello_from_bin


def main() -> None:
    print(hello_from_bin())

上記のコードでは、Hello from example-ext!という文字列を返すRustのhello_from_bin()関数を、Pythonの__init__.pymain関数で呼び出し、返り値の文字列をPrint出力しています。

hello_from_bin()のインポート文はfrom example_ext._core import hello_from_binですが、この_coreの部分を変更したい場合は、lib.rsの他にCargo.tomlも修正する必要があります。

Cargo.toml
[package]
name = "example_ext"
version = "0.1.0"
edition = "2021"

[lib]
name = "_core" # => ここを変える
# "cdylib" is necessary to produce a shared library for Python to import from.
crate-type = ["cdylib"]

[dependencies]
# "extension-module" tells pyo3 we want to build an extension module (skips linking against libpython.so)
# "abi3-py39" tells pyo3 (and maturin) to build using the stable ABI with minimum Python version 3.9
pyo3 = { version = "0.22.4", features = ["extension-module", "abi3-py39"] }

Hello World 実行

以下でビルドとsrc/__init__.pymain関数の実行を同時に行います。
この時、プロジェクト用の仮想環境が.venv配下に作成されます。また、src/example_ext配下にRustのバイナリ(_core.pyd)が作成されます。

>uv run --directory src/example_ext example-ext
Using CPython 3.12.1 interpreter at: C:\Python312\python.exe
Creating virtual environment at: C:\path\example-ext\.venv
   Built example-ext @ file:///C:/path/example-ext
Installed 1 package in 21ms
Hello from example-ext!

ビルドは初回のみで、2回目の実行以降はHello ...のみ出力されます。

>uv run --directory src/example_ext example-ext
Hello from example-ext!

なお、lib.rsの内容を変更し、再ビルドする場合はuv run実行時に--reinstallオプションを加える必要があります。以下は、Hello from example-ext!という文字列をHello World!に変更した例です。

> xuv run --reinstall --directory src/example_ext example-ext
   Built example-ext @ file:///C:/path/example-ext
Uninstalled 1 package in 2ms
Installed 1 package in 18ms
Hello World!
3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?