|
デフォルトのPyO3アプリケーションでは、pdoc3によってAPIドキュメントを生成すると、「モジュール名.モジュール名」というサブモジュールが出てくる。
どうやら、ピリオドの左側のモジュール名はPythonとしてのモジュール名(パッケージ名)で、右側のモジュール名はRustで定義したモジュールの名前のようだ。
なので、Rustのモジュール名をアンダースコアから始めてやれば、Pythonではprivate扱いになり、APIドキュメントに出て来なくなる。
なお、env_loggerを使ってログ出力を制御している場合、環境変数RUST_LOGに「モジュール名=info」のようなフィルター条件が指定できるのだが、このモジュール名もアンダースコア付きのものを指定することになる。[2026-02-24]
Rustモジュールをアンダースコアから始まる名前に変更する例。
まず、普通のPyO3プロジェクトを作成する。
uv run maturin new hidden-example
次に、Rustのモジュール名を変更する。
use pyo3::prelude::*;
/// A Python module implemented in Rust.
#[pymodule]
mod _hidden_example { // モジュール名の先頭にアンダースコアを追加
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())
}
}
Cargo.tomlのライブラリー名も変更する。
〜
[lib]
name = "_hidden_example" // モジュール名の先頭にアンダースコアを追加
crate-type = ["cdylib"]
〜
pyproject.tomlに[tool.maturin]を追加し、モジュール名を指定する。
同時に、プロジェクトの構成をPython/Rust混合構成に変更する。
〜
[tool.uv]
cache-keys = [{ file = "pyproject.toml" }, { file = "src/**/*.rs" }, { file = "Cargo.toml" }, { file = "Cargo.lock" }, { file = "python/**/*.py" }]
[tool.maturin]
module-name = "hidden_example._hidden_example" // モジュール名の指定
python-source = "python" // Python/Rust混合構成の指定
Python/Rust混合構成用に、pythonディレクトリーを作成し、Pythonモジュール名/__init__.pyを用意する。
"""
Rustモジュールを隠す実験
"""
from ._hidden_example import *
__all__ = [name for name in globals() if not name.startswith("_")]
> cd hidden-example > uv run python >>> import hidden_example >>> hidden_example.sum_as_string(1, 2) '3'
普通のPyO3プロジェクトと同様に、Pythonモジュール名で関数が呼べる。
pdoc3でAPIドキュメントを作成する方法も同じ。
> cd hidden-example > uv run pdoc hidden_example -o docs --html --force
サブモジュールを追加してみる。
Rustのコードは、通常と変わらない。
use pyo3::prelude::*;
/// 別ファイルのサブモジュール
#[pymodule]
pub(crate) mod sub {
use pyo3::prelude::*;
/// 別ファイルのサブモジュールのクラス1
#[pyclass]
pub struct SubClass1 {}
#[pymethods]
impl SubClass1 {
/// コンストラクター
#[new]
fn new() -> Self {
SubClass1 {}
}
fn show(&self) {
println!("SubClass1.show");
}
}
}
use pyo3::{exceptions::PyException, *};
/// 例外モジュール
#[pymodule]
pub(crate) mod error {
#[pymodule_export]
use super::{MyError1, MyError2, MyError3};
}
create_exception!(hidden_example.error, MyError1, PyException, "エラー1");
create_exception!(hidden_example.error, MyError2, PyException, "エラー2");
create_exception!(hidden_example.error, MyError3, MyError1, "エラー3");
use pyo3::prelude::*; mod error; mod sub;
/// A Python module implemented in Rust.
#[pymodule]
mod _hidden_example {
use pyo3::prelude::*;
#[pymodule_export]
use super::sub::sub;
#[pymodule_export]
use super::error::error;
#[pyfunction]
pub fn raise1() -> PyResult<()> {
use crate::error::MyError1;
Err(MyError1::new_err("test1"))
}
}
Pythonのコードは、Rustモジュールを使用する記述が必要。
from hidden_example._hidden_example import sub as _rust
for _name in _rust.__all__:
globals()[_name] = getattr(_rust, _name)
__all__ = _rust.__all__
from hidden_example._hidden_example import error as _rust
for _name in _rust.__all__:
globals()[_name] = getattr(_rust, _name)
__all__ = _rust.__all__
呼び出す側(Python)は、通常と変わらない。
> cd hidden-example
> uv run python
>>> import hidden_example
>>> s1 = hidden_example.sub.SubClass1()
>>> s1.show()
SubClass1.show
>>> try:
... hidden_example.raise1()
... except hidden_example.error.MyError1 as e:
... print(f"1: {e}")
...
1: test1
pdoc3でAPIドキュメントも作成できる。
> cd hidden-example > uv run pdoc hidden_example -o docs --html --force
pyo3-stub-genによる型スタブファイルの作成も、通常と同様に行える。
クラスや関数に付ける属性は通常と同じ。(Pythonとしてのモジュール名を付ける)
#[gen_stub_pyclass]
#[pyclass(module = "hidden_example.sub")]
pub struct SubClass1 {}
#[gen_stub_pyfunction(module = "hidden_example")]
#[pyfunction]
pub fn raise1() -> PyResult<()> {
use crate::error::MyError1;
Err(MyError1::new_err("test1"))
}
use pyo3_stub_gen::create_exception; create_exception!(hidden_example.error, MyError1, PyException, "エラー1"); create_exception!(hidden_example.error, MyError2, PyException, "エラー2"); create_exception!(hidden_example.error, MyError3, MyError1, "エラー3");
use pyo3::prelude::*; use pyo3_stub_gen::define_stub_info_gatherer;
#[pymodule]
mod _hidden_example {
〜
}
define_stub_info_gatherer!(stub_info);
stub_gen.rsも通常と同じ。(ただ、アンダースコア付きのモジュール名になる)
use pyo3_stub_gen::Result;
fn main() -> Result<()> {
let stub = _hidden_example::stub_info()?;
stub.generate()?;
Ok(())
}
型スタブファイルの生成方法も同じ。
> cd hidden-example > cargo run --bin stub_gen