Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

前記事 の続きです.

中規模以上のパッケージの場合, 関数を複数のモジュールに分けたくなると思います (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()
こんにちは, 世界!
>>> 
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away