Reputation: 396
How can I convert a traceback object to its string representation in CPython? I tried this but the output is not very useful.
PyObject *type, *value, *traceback;
PyErr_Fetch(&type, &value, &traceback);
PyObject* strTrace = PyObject_Repr(traceback);
pyStrTrace = PyUnicode_AsEncodedString(strTrace, "utf-8", "strict");
Py_XDECREF(strTrace);
const char* sTrace = PyBytes_AS_STRING(pyStrTrace);
Content of sTrace
:
<traceback object at 0x000002594A5CC598>
Upvotes: 2
Views: 677
Reputation: 396
One comment suggested to import traceback
python module which would most certainly work well but I prefer a C++ only solution so I came up with this snippet. Hopefully, someone finds it useful.
First include Python's <frameobject.h>
if (PyTraceBack_Check(traceback))
{
PyTracebackObject* traceRoot = (PyTracebackObject*)traceback;
PyTracebackObject* pTrace = traceRoot;
while (pTrace != NULL)
{
PyFrameObject* frame = pTrace->tb_frame;
PyCodeObject* code = frame->f_code;
int lineNr = PyFrame_GetLineNumber(frame);
const char *sCodeName = PyUnicode_AsUTF8(code->co_name);
const char *sFileName = PyUnicode_AsUTF8(code->co_filename);
printf("at %s (%s:%d); ", sCodeName, sFileName, lineNr);
pTrace = pTrace->tb_next;
}
}
As of Python 3.11 frame->f_code
is nolonger possible (PyFrameObject was moved private). It's suggested in the changelog that PyFrame_GetCode(frame)
is used instead.
Likewise, this removes the need to include <frameobject.h>
For backwards compatibility you can implement this function yourself:
#if PY_VERSION_HEX < 0x030900B1
#include <frameobject.h>
static inline PyCodeObject* PyFrame_GetCode(PyFrameObject *frame)
{
Py_INCREF(frame->f_code);
return frame->f_code;
}
#endif
Upvotes: 2