LoginSignup
4
4

More than 3 years have passed since last update.

[Rust] PyO3 でモジュール構造を持つ Python パッケージ

Posted at

前記事 の続きです.

中規模以上のパッケージの場合, 関数を複数のモジュールに分けたくなると思います (SciPy の scipy.optimize, scipy.integrate のように). ほぼ前回の記事通りですが, 若干ハマった部分があるので詳しく書いておきます.

モジュールの作成

具体的に英語と日本語で hello world を出力する language パッケージをつくってみます. まずはモジュールを普通につくります.

src/en.rs
use pyo3::prelude::*;
use pyo3::wrap_pyfunction;

#[pyfunction]
fn hello() -> PyResult<()> {
    println!("Hello, world!");
    Ok(())
}

#[pymodule]
fn english(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_wrapped(wrap_pyfunction!(hello))?;
    Ok(())
}
src/ja.rs
use pyo3::prelude::*;
use pyo3::wrap_pyfunction;


#[pyfunction]
fn hello() -> PyResult<()> {
    println!("こんにちは, 世界!");
    Ok(())
}

#[pymodule]
fn japanese(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_wrapped(wrap_pyfunction!(hello))?;
    Ok(())
}

ここで, 本体 (src/lib.rs) から参照することになる english, japanese 関数に pub を付ける必要はありません. というのも, #[pymodule] アトリビュートによりラッパー関数が自動的に生成され, そちらを読み込みに行くからです. その結果, 本体は次のようなコードになります.

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

mod en;
use en::*;

mod ja;
use ja::*;

#[pymodule]
fn language(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_wrapped(wrap_pymodule!(english))?;
    m.add_wrapped(wrap_pymodule!(japanese))?;

    Ok(())
}

ここで例えば use en::english; とするとコンパイルエラーになります. これは, 上で指摘したように, language 関数内で en::english 関数を呼び出しているように見えますが, wrap_pymodule マクロのために実際に呼び出している関数は en::PyInit_english 関数だからです (なのでこの関数を直接 use しても動きます).

Python から呼び出し

Cargo.toml やコンパイル, .so ファイルの配置などは前記事通りです.

$ python3
Python 3.7.2 (default, Jan 24 2019, 15:36:28)
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import language
>>> 
>>> language.english.hello()
Hello, world!
>>> language.japanese.hello()
こんにちは, 世界!
>>> 
4
4
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
4
4