traceback over C API - still not working...

Sami Vaisanen ensiferum_ at hotmail.com
Sat Oct 20 13:47:52 EDT 2007


This is becoming utterly painful process.... I found out that the return
value from "format_exception" function is NOT a list, i.e. PyList_Check()
fails. PySequence_Check() succeeds but then PySequence_List() gives me
back -1. So wtf?

I must say the API is crap on this part. Im trying to get error
information regarding previous error and if all i get back is another
error indicator, then what am I supposed to do? Recursive error handling?
Sounds like da bomb!

The API should have two levels of error handling. First level should
expose a conventional error code mechanism for checking for bad params
etc. Only if the error code says that there was a python error during
evaluation/compilation should one need to use this mechanism. 

Just my two cents.

Thanks for help.



void get_python_error_info(string& info)
{
    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)
    {
        PyErr_Clear();
        return;
    }
    PyObject* list = NULL;
    if (trace)
    {
        py_ref fun(PyObject_GetAttrString(module.get(), "format_exception"));
        if (fun)
            list = PyObject_CallFunctionObjArgs(type, value, trace, NULL);
        PyErr_Clear();
    }
    else
    {
        py_ref fun(PyObject_GetAttrString(module.get(), "format_exception_only"));
        if (fun)
            list = PyObject_CallFunctionObjArgs(type, value, NULL);
        PyErr_Clear();
    }
    if (list && PySequence_Check(list))
    {
        Py_ssize_t len = PySequence_Size(list);
          
        for (Py_ssize_t i=0; i<len; ++i)
        {
              // bla bla
        }
    }
    Py_XDECREF(list);
    PyErr_Clear();
}





> Hello group,
>
> I'm trying to get the Python exception information (message and  
> traceback)
> stored into a string in my C++ code. However all i get back is the string
> "None".

This is what you get (actually "None\n") when there is no error set.

> All the checks pass and all pointers get a value from the python
> API calls. I've also tried with a different function such as
> PyObject_CallFunctionObjArgs but the result is the same.

Since you already know the three components (type, value, trace), I'd use  
traceback.format_exception instead (and remove the PyErr_Restore call -  
I'm unsure if it works the way you expect it).
In this case you have to pass three arguments, so yes, use  
PyObject_CallFunctionObjArgs (remember the final NULL). Beware:  
format_exception returns a formatted list, not a string. You have to  
concatenate all the elements (either using ''.join or repeteadly calling  
PyString_Concat)

> 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";
> }




-- 
Gabriel Genellina




More information about the Python-list mailing list