Anton Kiselev Anton Kiselev - 4 months ago 8x
Python Question

How to get Python exception text

I want to embed python in my C++ application. I'm using Boost library - great tool. But i have one problem.

If python function throws an exception, i want to catch it and print error in my application or get some detailed information like line number in python script that caused error.

How can i do it? I can't find any functions to get detailed exception information in Python API or Boost.

try {
module=import("MyModule"); //this line will throw excetion if MyModule contains an error
} catch ( error_already_set const & ) {
//Here i can said that i have error, but i cant determine what caused an error
std::cout << "error!" << std::endl;

PyErr_Print() just prints error text to stderr and clears error so it can't be solution


Well, I found out how to do it.

Without boost (only error message, because code to extract info from traceback is too heavy to post it here):

PyObject *ptype, *pvalue, *ptraceback;
PyErr_Fetch(&ptype, &pvalue, &ptraceback);
//pvalue contains error message
//ptraceback contains stack snapshot and many other information
//(see python traceback structure)

//Get error message
char *pStrErrorMessage = PyString_AsString(pvalue);

And BOOST version

//some code that throws an error
}catch(error_already_set &){

    PyObject *ptype, *pvalue, *ptraceback;
    PyErr_Fetch(&ptype, &pvalue, &ptraceback);

    handle<> hType(ptype);
    object extype(hType);
    handle<> hTraceback(ptraceback);
    object traceback(hTraceback);

    //Extract error message
    string strErrorMessage = extract<string>(pvalue);

    //Extract line number (top entry of call stack)
    // if you want to extract another levels of call stack
    // also process traceback.attr("tb_next") recurently
    long lineno = extract<long> (traceback.attr("tb_lineno"));
    string filename = extract<string>(traceback.attr("tb_frame").attr("f_code").attr("co_filename"));
    string funcname = extract<string>(traceback.attr("tb_frame").attr("f_code").attr("co_name"));
... //cleanup here