Getting error message/trace over the C API

S

Sami Vaisanen

Hello group,

I'm writing a C++ based application that embeds the python engine. Now I
have a problem regarding exception/error information. Is there a way to
get the exception message and possibly the traceback into a string for
example? I've been eyeballing the PyErr_ module and it seems fairly
limited. In other words PyErr_Print() calls the right functions for
getting the exception information but unfortunately it is hardwired to
print this data directly into sys.stderr, and for an embedded application
this is completely inappropriate.

I have seen solutions that propose writing a custom Python class with
write method and using that to grab the output from sys.stderr and then
saving the data for example into a variable for later access, but unless
Im mistaken this solution (not only that it is extremely ugly) is not
thread safe. Even if a thread in my application is holding GIL, the lock
can be released by extensions/the interpreter and thus opens up a race
condition regarding that grabber object.

Please advice how to do this.

-sami
 
T

Thomas Heller

Sami said:
Hello group,

I'm writing a C++ based application that embeds the python engine. Now I
have a problem regarding exception/error information. Is there a way to
get the exception message and possibly the traceback into a string for
example? I've been eyeballing the PyErr_ module and it seems fairly
limited. In other words PyErr_Print() calls the right functions for
getting the exception information but unfortunately it is hardwired to
print this data directly into sys.stderr, and for an embedded application
this is completely inappropriate.

I have seen solutions that propose writing a custom Python class with
write method and using that to grab the output from sys.stderr and then
saving the data for example into a variable for later access, but unless
Im mistaken this solution (not only that it is extremely ugly) is not
thread safe. Even if a thread in my application is holding GIL, the lock
can be released by extensions/the interpreter and thus opens up a race
condition regarding that grabber object.

You should call 'import traceback; traceback.format_exc()' from your C code;
it returns a string (a 'PyObject *' that contains a string).

Thomas
 
D

Duncan Booth

Sami Vaisanen said:
Hello group,

I'm writing a C++ based application that embeds the python engine. Now I
have a problem regarding exception/error information. Is there a way to
get the exception message and possibly the traceback into a string for
example? I've been eyeballing the PyErr_ module and it seems fairly
limited. In other words PyErr_Print() calls the right functions for
getting the exception information but unfortunately it is hardwired to
print this data directly into sys.stderr, and for an embedded application
this is completely inappropriate.


Please advice how to do this.
All you have to do is call whatever functions you would call from Python.
e.g. from C you need to import traceback, then call getattr to get the
appropriate function (e.g. format_exc or format_exception), then just call
it.
 
S

Sami Vaisanen

All you have to do is call whatever functions you would call from Python.
e.g. from C you need to import traceback, then call getattr to get the
appropriate function (e.g. format_exc or format_exception), then just call
it.



void get_python_exception(string& message, string& traceback)
{
GIL g;

PyObject* type = NULL;
PyObject* value = NULL;
PyObject* trace = NULL;

PyErr_Fetch(&type, &value, &trace);

py_ref ref_type(type);
py_ref ref_value(value);
py_ref ref_trace(trace);

py_ref name(PyString_FromString("traceback"));
py_ref module(PyImport_Import(name.get()));
if (module)
{
py_ref fun(PyObject_GetAttrString(module.get(), "format_exc"));
if (fun)
{
PyErr_Restore(type, value, trace);
ref_type.release();
ref_value.release();
ref_trace.release();

py_ref ret(PyObject_CallObject(fun.get(), NULL));
if (ret && PyString_Check(ret.get()))
{
char* str = PyString_AsString(ret.get());
message = str;
traceback = "traceback not available";
return;
}
}
}
message = "message not available";
traceback = "traceback not available";
}

str evaluates to "None", any ideas what gives here? I've also tried to
call the traceback with a different function, such as
PyObject_CallFunctionObjArgs but the result is still same.

Thanks
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top