S-JIS[2025-12-14]

pyo3 PyDict型

Rustpyo3のPyDictのメモ。


概要

PyDictは、pyo3でPythonのdict(ディクショナリー)(Rust的にはHashMap)を表す型。

PyDictを操作するメソッドはPyDictMethodsトレイトで定義されている。

use pyo3::types::PyDict;
use pyo3::types::PyDictMethods;

PyO3 0.27では、PythonのdictをBound<PyDict>で受け取る。

use pyo3::{prelude::*, types::*};
#[pyfunction]
fn my_dict(dict: &Bound<PyDict>) -> PyResult<String> {
    println!("my_dict.len={}", dict.len());

    let mut s = String::new();
    for (key, value) in dict.iter() {
        let key: &str = key.extract()?;
        s.push_str(key);
        s.push_str("=");

        if value.is_instance_of::<PyString>() {
            let value: &str = value.extract()?;
            s.push_str(value);
        } else if value.is_instance_of::<PyInt>() {
            let value: i64 = value.extract()?;
            s.push_str(&value.to_string());
        } else {
            s.push_str("unknown-type");
        };

        s.push_str(", ");
    }

    Ok(s)
}

dict.iter()で取れるkey・valueはBound<PyAny>型なので、is_instance_ofメソッドで具体的な型を判定し、extractメソッドで変換する。

呼び出すPython側の例

    print(example_pyo3.my_dict({"key1":"value1", "key2": 123, "key3": 123.4}))

HashMapの例

dictの値の型が固定なのであれば、引数に直接HashMapを指定できる。

#[pyfunction]
fn my_dict(dict: HashMap<String, String>) -> PyResult<String> {
    println!("{:?}", dict);

    let mut s = String::new();
    for (key, value) in dict.iter() {
        s.push_str(key);
        s.push_str("=");
        s.push_str(value);
        s.push_str(", ");
    }

    Ok(s)
}

この例ではHashMapのキーと値の型がStringなので、呼び出すPython側で文字列以外を指定すると、実行時にエラーが発生する。


キーワード引数の例

Pythonの関数の**kwargsを受け取るには、PyO3 0.27ではシグネチャーを定義する。

use pyo3::{prelude::*, types::*};
#[pyfunction]
#[pyo3(signature = (arg1, **kwargs))]
fn my_kwargs(py: Python, arg1: String, kwargs: Option<Bound<PyDict>>) -> PyResult<String> {
    let mut s = arg1.clone();
    s.push_str("--");

    if let Some(dict) = kwargs {
        for (key, value) in dict.iter() {
            let key: &str = key.extract()?;
            s.push_str(key);
            s.push_str("=");

            if value.is_instance_of::<PyString>() {
                s.push_str(value.extract::<&str>()?);
            } else if value.is_instance_of::<PyInt>() {
                s.push_str(&value.extract::<i64>()?.to_string());
            } else {
                s.push_str("unsupported-type");
            }
            s.push_str(", ");
        }
    }

    Ok(s)
}

呼び出すPython側の例

    print(example_pyo3.my_kwargs("abc"))
    print(example_pyo3.my_kwargs("abc", key1="def", key2="ghi"))

pyo3へ戻る / Rustへ戻る / 技術メモへ戻る
メールの送信先:ひしだま