如何通过Python C API/pybind11创建并返回异常而非抛出
解决方案
首先你完全不需要走「设置异常→抓取异常→清除异常」的绕路逻辑:Python 中的异常本质就是普通的内置类,直接实例化即可得到异常实例,对应 C API 和 pybind11 都有非常简单的实现方式。
你现有代码的问题
你写的代码编译失败的核心原因是返回类型错误:PyExc_ValueError 是指向 Python 内置 ValueError 类型对象的全局指针,不是 C/C++ 层面的类型名,无法作为返回值类型使用,所有 Python 对象的引用统一用 PyObject* 接收即可。另外你整套异常设置、抓取的逻辑完全冗余,没有必要。
纯 Python C API 实现
直接调用 PyObject_CallFunction 实例化内置异常类即可,和 Python 层写 ValueError("错误信息") 的效果完全一致:
PyObject* some_fn() { // 直接实例化 ValueError,和Python层语法等价 PyObject* err_inst = PyObject_CallFunction( PyExc_ValueError, "s", "error in my function!!!" ); // 可选:如果需要给异常附加当前栈的traceback PyObject* frame = PyEval_GetFrame(); if (frame != NULL) { PyObject* tb = PyTraceBack_New(frame); PyException_SetTraceback(err_inst, tb); Py_DECREF(tb); } // 返回的是新引用,调用方用完需要负责Py_DECREF return err_inst; }
pybind11 场景更简单的实现
pybind11 已经对内置异常做了封装,直接构造异常对象返回即可,pybind11 会自动处理引用计数和类型转换,不会自动抛出异常:
#include <pybind11/pybind11.h> namespace py = pybind11; py::object some_fn() { return py::value_error("error in my function!!!"); }
返回的对象在Python层就是正常的ValueError实例,可以直接用isinstance判断,和你原来纯Python实现的逻辑完全兼容。
内容的提问来源于stack exchange,提问作者ghlecl
相关产品推荐
相关产品推荐

