我最近將一個正在處理的C++項目升級到Python 3.5.2(它是一個可執行文件,其編譯爲32位或64位) ,並且在兩個版本中具有相同的行爲)。C/C++ Python異常回溯未生成
我創造我自己的異常:
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;
}
到目前爲止,一切都很好。如果我用蟒蛇抓住它,一切都很好:
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)
打印正確的tracback到命令行。
然而,當我嘗試,我用PyErr_Fetch
做在C++/Python的類似的事情:
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, traceback\n";
fcn += " lines = []\n";
fcn += " lines = traceback.format_exception(exc_type, exc_value, exc_tb)\n";
fcn += " output = '\\n'.join(lines)\n";
fcn += " return output\n";
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++中的異常。