[C++-sig] Have error_already_set - now what?
Achim H.
achim-bpl at mol-net.com
Fri Jan 12 10:50:32 CET 2007
Am Donnerstag, 11. Januar 2007 18:50 schrieb Johan Johansson:
> It's probably just me missing something obvious, but I'm having a very hard
> time to get a useful error message when I catch an error_already_set in
> code calling a python function/method.
[..]
> What's a good way to find out what error occurred (exhaustively matching
> doesn't strike me as good).
I had the same problem and additionally, I did not want to pollute stderr as
my project has its own logging system. This hacked beast is what I came up
with. AFAIK, it works for Python 2.3 - 2.5 but as it's using python
internals, that's not something to be relied on for the future.
Achim.
typedef struct _traceback {
PyObject_HEAD
struct _traceback *tb_next;
struct _frame *tb_frame;
int tb_lasti;
int tb_lineno;
} PyTracebackObject; // stolen from python source, not in normal headers
std::string printTB(PyObject *f)
{
PyTracebackObject *tb = (PyTracebackObject *)f;
int err = 0;
std::ostringstream os;
while (tb != NULL && err == 0)
{
os << " File \x22"<<PyString_AsString(tb->tb_frame->f_code->co_filename)
<< "\x22, line "<<tb->tb_lineno<<", in "
<< PyString_AsString(tb->tb_frame->f_code->co_name)
<< "\n";
tb = tb->tb_next;
if (err == 0)
err = PyErr_CheckSignals();
}
os.flush();
return os.str();
}
std::string getPythonException()
{
PyObject* type = 0;
PyObject* value = 0;
PyObject* tb = 0;
PyErr_Fetch(&type,&value,&tb);
try {
handle<> type_o( allow_null(type) );
handle<> value_o(value);
handle<> tb_o( allow_null(tb) );
handle<> type_str(PyObject_Str(type_o.get()));
handle<> value_str(PyObject_Str(value_o.get()));
handle<> tb_str(PyObject_Str(tb_o.get()));
std::string ret = "Error in python execution:\n";
if (tb_str.get()!=0)
ret += "Traceback (most recent call last):\n" + printTB(tb_o.get());
std::string type_string = PyString_AsString(type_str.get());
if (type_string.find("exceptions.")==0)
type_string=type_string.substr(11);
ret += type_string + ": ";
ret += PyString_AsString(value_str.get());
ret += "\n";
return ret;
}
catch (error_already_set&)
{
return "Error during python exception elucidation.";
}
}
More information about the Cplusplus-sig
mailing list