You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PyO3中返回带Payload(负载)的自定义错误?

在PyO3中实现带负载的自定义错误

PyO3的官方示例大多仅返回简单字符串错误,但实际开发中常需要返回包含额外负载(比如错误元素及其位置信息)的自定义错误。以下是Python中的等价实现:

from dataclasses import dataclass

@dataclass
class NotIntError(Exception):
    item: object

    def __str__(self):
        return f"Expected int but found {type(self.item)}: {self.item}"

def validate_int(item):
    if not isinstance(item, int):
        raise NotIntError(item)

你的Rust代码思路方向正确,但有几处需要调整,以下是修正后的完整实现:

use pyo3::prelude::*;
use pyo3::types::PyInt;

// 自定义错误类,继承Python的Exception
#[pyclass(extends=PyException)]
#[derive(Debug)]
pub struct NotIntError {
    #[pyo3(get)] // 暴露item属性给Python访问
    item: Py<PyAny>,
}

#[pymethods]
impl NotIntError {
    // 初始化方法,规范错误实例的创建方式
    #[new]
    fn new(item: Py<PyAny>) -> Self {
        NotIntError { item }
    }

    // 实现字符串表示,符合Python的__str__行为
    fn __str__(&self, py: Python<'_>) -> PyResult<String> {
        let item_type = self.item.get_type(py).name()?;
        let item_str = self.item.str(py)?.to_string();
        Ok(format!("Expected int but found {}: {}", item_type, item_str))
    }
}

#[pyfunction]
pub fn validate_int(item: &Bound<'_, PyAny>) -> PyResult<()> {
    if !item.is_instance_of::<PyInt>() {
        // 创建自定义错误实例并抛出
        let error = NotIntError::new(item.into());
        Err(PyErr::new::<NotIntError, _>(error))
    } else {
        Ok(())
    }
}

// 模块注册,让Python能访问自定义错误和函数
#[pymodule]
fn my_module(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
    m.add_class::<NotIntError>()?;
    m.add_function(wrap_pyfunction!(validate_int, m)?)?;
    Ok(())
}

关键调整说明

  • 在#[pyclass]中添加extends=PyException,让自定义类成为Python Exception的子类,融入Python错误体系
  • 用#[pyo3(get)]标记item字段,允许Python代码直接访问错误实例的item属性
  • 实现#[new]方法,统一错误实例的创建逻辑
  • 在__str__中使用PyAny的str()方法获取符合Python风格的字符串表示,避免Debug格式的输出问题

使用效果

在Python中调用时,行为和你给出的Python实现完全一致:

import my_module

try:
    my_module.validate_int("hello")
except my_module.NotIntError as e:
    print(e)  # 输出: Expected int but found str: hello
    print(e.item)  # 输出: hello

内容的提问来源于stack exchange,提问作者drhagen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 10:28:17