C/C++ 未生成 Python 异常回溯
C/C++ Python exception traceback not being generated
我最近升级了一个我正在做的C++项目,它嵌入了python,从Python 3.4.3到Python 3.5.2(它是一个构建为32位或64位的可执行文件,并且在两个版本中具有相同的行为)。
我正在创建自己的异常:
static PyObject* MyException_type_obj = 0;
void setup(PyObject* module){
MyException_type_obj = PyErr_NewException("my_module.MyException", NULL, NULL);
PyObject* dict = PyModule_GetDict(module);
PyDict_SetItemString(dict, "MyException", MyException_type_obj);
}
然后在一些由python代码调用的C++代码中提出它:
static PyObject* RaiseIt(PyObject* self, PyObject* args)
{
PyErr_Format(Forever_Exception_type_obj, "Exit Requested");
return 0;
}
目前为止,一切都好。如果我在 python 中捕获它,一切都很好:
try:
my_module.raise_it()
except my_module.MyException:
import sys, traceback
exc_type, exc_value, exc_tb = sys.exc_info()
print(traceback.format_exception(exc_type, exc_value, exc_tb)
将正确的回溯打印到命令行。
但是,当我尝试在C++/Python中使用PyErr_Fetch
做类似的事情时:
std::string get_traceback(){
PyObject* type;
PyObject* value;
PyObject* traceback;
PyErr_Fetch(&type, &value, &traceback);
std::string fcn = "";
fcn += "def get_pretty_traceback(exc_type, exc_value, exc_tb):n";
fcn += " import sys, tracebackn";
fcn += " lines = []n";
fcn += " lines = traceback.format_exception(exc_type, exc_value, exc_tb)n";
fcn += " output = '\n'.join(lines)n";
fcn += " return outputn";
PyRun_SimpleString(fcn.c_str());
PyObject* mod = PyImport_ImportModule("__main__");
PyObject* method = PyObject_GetAttrString(mod, "get_pretty_traceback");
PyObject* outStr = PyObject_CallObject(method, Py_BuildValue("OOO", type, value, traceback));
std::string pretty = PyBytes_AsString(PyUnicode_AsASCIIString(outStr));
Py_DECREF(method);
Py_DECREF(outStr);
return pretty;
}
它崩溃了,我得到一个空outStr
.
获取一些其他详细信息
fcn += " lines = []n";
fcn += " try:n";
fcn += " lines = traceback.format_exception(exc_type, exc_value, exc_tb)n";
fcn += " except Exception as e:n";
fcn += " print('Exception while rendering a python exception for C')n";
fcn += " print(e)n";
fcn += " output = '\n'.join(lines)n";
给我神秘的错误消息:
'str' object has no attribute '__cause__'
顺便说一句,这在python 2.7中也不会发生(有与字符串相关的微小更改)。它只在 python 3.5 中为我服务。
同样的 C++ get_traceback() 函数适用于在 python 中启动的异常,但不适用于C++异常。
显然,在我的PyErr_Fetch
调用之后立即需要PyErr_NormalizeException
,这会将值从字符串转换为异常对象的实例。
PyObject* type;
PyObject* value;
PyObject* traceback;
PyErr_Fetch(&type, &value, &traceback);
PyErr_NormalizeException(&type, &value, &traceback); // Added line
...
修复了此问题。我不知道为什么来自 C++ 生成的异常的值与来自 python 的异常的值会更改该值,但这会处理它。
相关文章:
- 如何通过 pybind11 从 python 中的C++中捕获异常?
- Windows错误:异常:使用从C++到Python的ctypes创建DLL时出现访问冲突或Windows错误193
- 析构函数中的互斥锁C++在 Python 中调用 exit() 时会导致异常
- Python Director 类中的 Swig 异常
- C/C++ 未生成 Python 异常回溯
- Cython -Python异常传播C 例外
- 包含python.h和boost/python.hpp的C++导致SEH异常
- 将异常处理从 python 转换为 C++
- Python 子进程异常处理
- Boost.Python自定义异常类
- 为什么 Python 没有捕获C++中引发的异常?
- 如何使c++像python一样给出详细的异常信息
- 在c++中捕捉Python异常
- Python输入和异常vs. c++
- 将内嵌Python异常传播到c++
- Python异常:在调试支持stl的c++代码时,索引超出范围
- 如何通过boost::python捕获python站点的自定义异常
- Java, c++, Python中的异常模型
- 使用SWIG动态地将自定义C++异常重新考虑为Python异常
- 为什么我丢失异常与SWIG, c++, python