views:

670

answers:

2

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

+1  A: 

In the Python C API, PyObject_Str returns a new reference to a Python string object with the string form of the Python object you're passing as the argument -- just like str(o) in Python code. Note that the exception object does not have "information like line number" -- that's in the traceback object (you can use PyErr_Fetch to get both the exception object and the traceback object). Don't know what (if anything) Boost provides to make these specific C API functions easier to use, but, worst case, you could always resort to these functions as they are offered in the C API itself.

Alex Martelli
thanks a lot, Alex. I was looking a way to make it without direct calling of PyAPI - i thougth Boost can deal with exceptions, but Boost can't :(
Anton Kiselev
@Anton, glad I helped, so what about upvoting and accepting this answer?-) Use the checkmark icon under the number of upvotes for this answer (currently 0;-).
Alex Martelli
A: 

Well, i founded 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

try{
//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
Anton Kiselev