I'm trying to retreive an exception + traceback printout in a C extension.
I want to do the same thing as
try:
print(0/0) # Throw a divide by zero
except:
traceback_string = traceback.format_exc()
but in the C API so I can pass the resulting string over to the C side.
My attempt is as follows:
PyObject *result, *output;
PyObject *Python3Traceback;
char *string;
Python3Traceback = PyImport_ImportModule("traceback");
result = PyRun_String("0/0", Py_eval_input, globals, globals);
if (result == 0) {
output = PyObject_CallMethod(Python3Traceback, "format_exc", "()");
string = PyUnicode_AsUTF8AndSize(output, &length);
}
However string always comes back with the value NoneType: None, which is the same as calling `traceback.format_exc' outside an except clause. How can I get at the formatted traceback for the exception that caused result to be 0 ?
I've also tried
PyObject *type, *value, *traceback;
PyErr_Fetch(&type, &value, &traceback);
output = PyObject_ASCII(value);
string = PyUnicode_AsUTF8AndSize(output, &length);
Which does get the right values, (value is the string division by zero), but then I can't work out how to get the full traceback printout.
I got the result I was after in the end with the following:
PyErr_Fetch(&type, &value, &traceback);
PyErr_NormalizeException(&type, &value, &traceback);
if (traceback2 != NULL) {
PyException_SetTraceback(value, traceback);
}
output = PyObject_CallMethod(Python3Traceback, "format_exception", "(OOO)", type, value, traceback);
concat = PyObject_CallMethod(Py_BuildValue("s", ""), "join", "(O)", output);
string = PyUnicode_AsUTF8AndSize(concat, &length);
But I still don't know why calling PyErr_Fetch gets me the current exception information, while calling PyObject_CallMethod(Python3Traceback, "format_exc"...) gives None.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With