Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Q: how to get python error message?

776 views
Skip to first unread message

Karsten Ballueder

unread,
Jun 10, 1998, 3:00:00 AM6/10/98
to

Hello,

I am using python embedded in a windowed C++ application.
For this, the PyErr_Print() function is not too useful, and I wonder
whether there is a similarly simple function, something like
char *PyErr_GetErr() to obtain the string of the error message as
PyErr_Print() would print it.

I searched the docs and didn't find anything. Looking at the source of
PyErr_Print() I guess there might not be a simple solution - do I
really need to write my own?

Thanks a lot in advance,
--
Karsten Ballüder http://Ballueder.home.ml.org/ mailto:Ball...@usa.net
Physics Department, Heriot-Watt University, Edinburgh, EH14 4AS, Scotland
"In a world without fences, who needs Gates?"

Guido van Rossum

unread,
Jun 10, 1998, 3:00:00 AM6/10/98
to

> I am using python embedded in a windowed C++ application.
> For this, the PyErr_Print() function is not too useful, and I wonder
> whether there is a similarly simple function, something like
> char *PyErr_GetErr() to obtain the string of the error message as
> PyErr_Print() would print it.
>
> I searched the docs and didn't find anything. Looking at the source of
> PyErr_Print() I guess there might not be a simple solution - do I
> really need to write my own?

The simplest solution is accessible from Python. The module traceback
contains various functions that emulate PyErr_Print(). You can pass
a StringIO instance as the output file to get it as a string. Calling
this from C++ would be simple enough.

--Guido van Rossum (home page: http://www.python.org/~guido/)

Mark Hammond

unread,
Jun 11, 1998, 3:00:00 AM6/11/98
to

Guido van Rossum wrote in message
<1998061017...@eric.CNRI.Reston.Va.US>...
> ...


>The simplest solution is accessible from Python. The module traceback
>contains various functions that emulate PyErr_Print(). You can pass
>a StringIO instance as the output file to get it as a string. Calling
>this from C++ would be simple enough.

Simple enough is true, but it is a bit fiddly. Below is my latest
version of code I use. (But Id be very interested to see how much
easier it is using the new C++-SIG stuff!)

Mark.

/*--
GetPythonErrorMessage

Assuming a Python error has occurred in the current thread state,
return a "char *" which is a formatted traceback, or NULL if the
traceback can not be obtained.

If a non-NULL value is returned, it should be passed to "free()" when
it is no longer needed (the string is allocated using strdup!)

Uses the built-in library modules cStringIO and traceback, so if the
core Python library is not setup correctly, this will not work.

Regardless of if the function succeeds, the exception state id
always restored to how it was when we were entered. The caller
may still wish to call PyErr_Clear() to clean it all up.

Mark Hammond - Jan 1998
--*/
#define GPEM_ERROR(what) {errorMsg = "<Error getting traceback - " ##
what ## ">";goto done;}


char *GetPythonErrorMessage()
{
char *result = NULL;
char *errorMsg = NULL;
PyObject *modStringIO = NULL;
PyObject *modTB = NULL;
PyObject *obFuncStringIO = NULL;
PyObject *obStringIO = NULL;
PyObject *obFuncTB = NULL;
PyObject *argsTB = NULL;
PyObject *obResult = NULL;
PyObject *exc_typ, *exc_val, *exc_tb;
/* Fetch the error state now before we cruch it */
PyErr_Fetch(&exc_typ, &exc_val, &exc_tb);

/* Import the modules we need - cStringIO and traceback */
modStringIO = PyImport_ImportModule("cStringIO");
if (modStringIO==NULL) GPEM_ERROR("cant import cStringIO");
modTB = PyImport_ImportModule("traceback");
if (modTB==NULL) GPEM_ERROR("cant import traceback");

/* Construct a cStringIO object */
obFuncStringIO = PyObject_GetAttrString(modStringIO, "StringIO");
if (obFuncStringIO==NULL) GPEM_ERROR("cant find cStringIO.StringIO");
obStringIO = PyObject_CallObject(obFuncStringIO, NULL);
if (obStringIO==NULL) GPEM_ERROR("cStringIO.StringIO() failed");

/* Get the traceback.print_exception function, and call it. */
obFuncTB = PyObject_GetAttrString(modTB, "print_exception");
if (obFuncTB==NULL) GPEM_ERROR("cant find traceback.print_exception");
argsTB = Py_BuildValue("OOOOO",
exc_typ ? exc_typ : Py_None,
exc_val ? exc_val : Py_None,
exc_tb ? exc_tb : Py_None,
Py_None,
obStringIO);
if (argsTB==NULL) GPEM_ERROR("cant make print_exception arguments");

obResult = PyObject_CallObject(obFuncTB, argsTB);
if (obResult==NULL) GPEM_ERROR("traceback.print_exception() failed");

/* Now call the getvalue() method in the StringIO instance */
Py_DECREF(obFuncStringIO);
obFuncStringIO = PyObject_GetAttrString(obStringIO, "getvalue");
if (obFuncStringIO==NULL) GPEM_ERROR("cant find getvalue function");
Py_DECREF(obResult);
obResult = PyObject_CallObject(obFuncStringIO, NULL);
if (obResult==NULL) GPEM_ERROR("getvalue() failed.");

/* And it should be a string all ready to go - duplicate it. */
if (!PyString_Check(obResult))
GPEM_ERROR("getvalue() did not return a string");
result = strdup(PyString_AsString(obResult));
done:
if (result==NULL && errorMsg != NULL)
result = strdup(errorMsg);
Py_XDECREF(modStringIO);
Py_XDECREF(modTB);
Py_XDECREF(obFuncStringIO);
Py_XDECREF(obStringIO);
Py_XDECREF(obFuncTB);
Py_XDECREF(argsTB);
Py_XDECREF(obResult);

/* Restore the exception state */
PyErr_Restore(exc_typ, exc_val, exc_tb);
return result;
}


Sundar Ramamoorthy

unread,
Jun 12, 1998, 3:00:00 AM6/12/98
to

"Mark Hammond" <MHam...@skippinet.com.au> writes:

I have an application which has Python(v1.4) embedded in it. I tried using
this and it complains not being able to import cStringIO. Obviously python
was not built with this module. Is there any other way to accomplish the same
with version 1.4.

Thanks,
Sundar.R
--
Sundar Ramamoorthy (312) 554-5728
Software Consultant rama...@il.us.swissbank.com
Swiss Bank Corp. Chicago, IL.

Guido van Rossum

unread,
Jun 12, 1998, 3:00:00 AM6/12/98
to

> I have an application which has Python(v1.4) embedded in it. I tried using
> this and it complains not being able to import cStringIO. Obviously python
> was not built with this module. Is there any other way to accomplish the same
> with version 1.4.

Yes -- import "StringIO" instead of "cStringIO". Should be a one-line
change in that code.

0 new messages