在 Rust 的 pyO3 中,如何表示在 Python 中实现的自定义 Python 类,以便 pyo3 结构体可以检查类型?

问题描述 投票:0回答:1

我正在编写一个自定义 MessagePack 序列化程序,以添加到广泛使用 MessagePack 的旧 Python 项目中。特别是,我经常建立一些需要一次性序列化的对象列表,但 GIL 阻止了这种情况,所以我想使用 Rust 来做到这一点,并在其他方面保持快速。

我已经获得了以这种方式序列化的基本 Python 类型,但我也想序列化我的 Python 应用程序所具有的一些自定义类,并且不希望将它们移植到 Rust 中,尽管 pyO3 会让这变得容易这样做,我对添加对此 Rust 代码的硬依赖感到紧张,并且希望回退到标准 Python MessagePack 库。

所以我首先编写一个结构体来表示单例:

struct PyFinalRule(PyAny);
unsafe impl PyTypeInfo for PyFinalRule {
    const NAME: &'static str = "FinalRule";
    const MODULE: Option<&'static str> = Option::Some("LiSE.util");
    type AsRefTarget = PyAny;

    fn type_object_raw(py: Python<'_>) -> *mut PyTypeObject {
        let modu = py.import("LiSE.util").unwrap();
        let final_rule = modu.getattr("FinalRule").unwrap();
        final_rule.get_type_ptr()
    }
}
unsafe impl PyNativeType for PyFinalRule {}

我期望能够使用

PyFinalRule::is_type_of
来检查
PyAny
对象何时确实是
FinalRule
的实例。相反,当传递
PyFinalRule::is_type_of
单例的一个实例时,
false
始终返回
FinalRule
。当传递
true
类型对象时,它返回
FinalRule
,但这不是很有用,因为应用程序序列化的是实例而不是类型对象。

如何让

PyFinalRule::is_type_of
真正检查类型?

python rust msgpack pyo3
1个回答
0
投票

对于我来说,我会建议您获取自定义类的 Python 类型对象。您可以在函数中或作为序列化逻辑的一部分来执行此操作,如下所示

use pyo3::prelude::*;
use pyo3::types::PyType;

fn get_final_rule_type(py: Python) -> Py<PyType> {
    let modu = py.import("LiSE.util").expect("Failed to import module");
    let final_rule = modu.getattr("FinalRule").expect("Failed to get FinalRule class");
    final_rule.extract::<Py<PyType>>().expect("Failed to extract PyType")
}

然后像这样检查实例类型

fn is_final_rule_instance(obj: &PyAny, final_rule_type: &PyType) -> PyResult<bool> {
    obj.is_instance_of(final_rule_type)
}

#https://pyo3.rs/main/doc/pyo3/types/struct.pyany

在你的序列化逻辑中

#[pyfunction]
fn serialize_custom(py: Python, obj: &PyAny) -> PyResult<Vec<u8>> {
    let final_rule_type = get_final_rule_type(py);
    
    if is_final_rule_instance(obj, &final_rule_type)? {
        // Perform custom serialization for FinalRule instances
    } else {
        // Handle other types
    }

    // ... rest of your serialization logic ...
}


© www.soinside.com 2019 - 2024. All rights reserved.