S-JIS[2025-12-14/2025-12-20]

pyo3 PyAny型

Rustpyo3のPyAnyのメモ。


概要

PyAnyは、pyo3でPythonのオブジェクトを表す型。

use pyo3::types::PyAny;

ちなみに、PyObjectはPy<PyAny>だが、pyo3 0.26.0で非推奨になったらしい。
(直接Py<PyAny>を使えということらしい>)


型を判定する例

PyAnyがPythonで具体的にどんな型だったのかは、is_instance_ofメソッドで判定できる。

use pyo3::{prelude::*, types::*};
#[pyfunction]
fn my_type(value: Bound<PyAny>) -> PyResult<&str> {
    let r = if value.is_instance_of::<PyString>() {
        "PyString"
    } else if value.is_instance_of::<PyInt>() {
        "PyInt"
    } else if value.is_instance_of::<PyFloat>() {
        "PyFloat"
    } else {
        "unknown-type"
    };

    Ok(r)
}

型を変換する例

PyAnyから具体的な型へは、extractメソッドで変換できる。

use pyo3::{prelude::*, types::*};
#[pyfunction]
fn my_extract(value: Bound<PyAny>) -> PyResult<String> {
    let r = if value.is_instance_of::<PyString>() {
        let value: &str = value.extract()?;
        format!("PyString: {}", value)
    } else if value.is_instance_of::<PyInt>() {
        let value: i64 = value.extract()?;
        format!("PyInt: {}", value)
    } else if value.is_instance_of::<PyFloat>() {
        let value: f64 = value.extract()?;
        format!("PyFloat: {}", value)
    } else {
        "unknown-type".to_string()
    };

    Ok(r)
}

Rustの型からPyAnyへ変換するには、一旦Bound<T>に変換する。[2025-12-20]

#[pymodule]
mod example_pyo3 {
    use pyo3::{prelude::*, types::*};

    #[pyfunction]
    fn return_example(py: Python, arg1: Option<i32>, arg2: Option<&str>) -> PyResult<Py<PyAny>> {
        if let Some(n) = arg1 {
            let n = n.into_pyobject(py)?; // Bound<PyInt>
            let n = n.into_any();         // Bound<PyAny>
            return Ok(n.unbind());
        }
        if let Some(s) = arg2 {
            let s = s.into_pyobject(py)?; // Bound<PyString>
            let s = s.into_any();         // Bound<PyAny>
            return Ok(s.unbind());
        }

        Ok(py.None())
    }
}

または

    #[pyfunction]
    fn return_example(py: Python, arg1: Option<i32>, arg2: Option<&str>) -> PyResult<Py<PyAny>> {
        if let Some(n) = arg1 {
            let n = n.into_pyobject(py)?; // Bound<PyInt>
            return Ok(n.into());
        }
        if let Some(s) = arg2 {
            let s = s.into_pyobject(py)?; // Bound<PyString>
            return Ok(s.into());
        }

        Ok(py.None())
    }

または

    #[pyfunction]
    fn return_example<'py>(py: Python<'py>, arg1: Option<i32>, arg2: Option<&str>) -> PyResult<Bound<'py, PyAny>> {
//  fn return_example(py: Python, arg1: Option<i32>, arg2: Option<String>) -> PyResult<Bound<PyAny>> {
        if let Some(n) = arg1 {
            let n = n.into_pyobject(py)?; // Bound<PyInt>
            return Ok(n.into_any());
//          return Ok(n.as_any().clone()); // n.as_any(): &Bound<PyAny>
        }
        if let Some(s) = arg2 {
            let s = s.into_pyobject(py)?; // Bound<PyString>
            return Ok(s.into_any());
//          return Ok(s.as_any().clone()); // s.as_any(): &Bound<PyAny>
        }

        Ok(py.None().into_bound(py))
//      Ok(py.None().bind(py).clone()) // py.None().bind(py): &Bound<PyAny>
    }

Pythonでの実行例

> uv run python
>>> import example_pyo3
>>> print(example_pyo3.return_example(None, None))
None
>>> example_pyo3.return_example(None, "abc") 
'abc'
>>> example_pyo3.return_example(123, "abc") 
123

>>> example_pyo3.return_example(None, None) is None
True
>>> isinstance(example_pyo3.return_example(None, "abc"), str) 
True
>>> isinstance(example_pyo3.return_example(None, "abc"), int)
False
>>> isinstance(example_pyo3.return_example(123, "abc"), str) 
False
>>> isinstance(example_pyo3.return_example(123, "abc"), int) 
True

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