Index: Python/errors.c =================================================================== --- Python/errors.c (revision 73446) +++ Python/errors.c (working copy) @@ -642,7 +642,60 @@ } +/* Returns the exception string as a new + PyUnicode object or NULL if the conversion failed */ +PyObject * +PyErr_AsUnicode(void) +{ + PyObject *string_io = NULL; + PyObject *string_io_buf = NULL; + PyObject *string_io_mod; + PyObject *string_io_getvalue; + + PyObject *error_type, *error_value, *error_traceback; + + if (!PyErr_Occurred()) + return NULL; + + PyErr_Fetch(&error_type, &error_value, &error_traceback); + + PyErr_Clear(); + + /* import io + * string_io = io.StringIO() + */ + if(! (string_io_mod= PyImport_ImportModule("io")) ) { + PyErr_Clear(); + return NULL; + } + else if (! (string_io= PyObject_CallMethod(string_io_mod, "StringIO", NULL))) { + PyErr_Clear(); + Py_DECREF(string_io_mod); + return NULL; + } + else if (! (string_io_getvalue= PyObject_GetAttrString(string_io, "getvalue"))) { + PyErr_Clear(); + Py_DECREF(string_io_mod); + Py_DECREF(string_io); + return NULL; + } + + PyErr_DisplayEx(error_type, error_value, error_traceback, string_io); + + /* clear the error */ + PyErr_Restore(error_type, error_value, error_traceback); + PyErr_Clear(); + + string_io_buf = PyObject_CallObject(string_io_getvalue, NULL); + + Py_DECREF(string_io_mod); + Py_DECREF(string_io_getvalue); + Py_DECREF(string_io); /* free the original reference */ + + return string_io_buf; +} + PyObject * PyErr_NewException(const char *name, PyObject *base, PyObject *dict) { Index: Python/pythonrun.c =================================================================== --- Python/pythonrun.c (revision 73446) +++ Python/pythonrun.c (working copy) @@ -1593,10 +1593,9 @@ } void -PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb) +PyErr_DisplayEx(PyObject *exception, PyObject *value, PyObject *tb, PyObject *f) { PyObject *seen; - PyObject *f = PySys_GetObject("stderr"); if (f == Py_None) { /* pass */ } @@ -1616,6 +1615,13 @@ } } +void +PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb) +{ + PyObject *f = PySys_GetObject("stderr"); + PyErr_DisplayEx(exception, value, tb, f); +} + PyObject * PyRun_StringFlags(const char *str, int start, PyObject *globals, PyObject *locals, PyCompilerFlags *flags) Index: Include/pythonrun.h =================================================================== --- Include/pythonrun.h (revision 73446) +++ Include/pythonrun.h (working copy) @@ -70,6 +70,7 @@ PyAPI_FUNC(void) PyErr_Print(void); PyAPI_FUNC(void) PyErr_PrintEx(int); PyAPI_FUNC(void) PyErr_Display(PyObject *, PyObject *, PyObject *); +PyAPI_FUNC(void) PyErr_DisplayEx(PyObject *, PyObject *, PyObject *, PyObject *); /* Py_PyAtExit is for the atexit module, Py_AtExit is for low-level * exit functions. Index: Include/pyerrors.h =================================================================== --- Include/pyerrors.h (revision 73446) +++ Include/pyerrors.h (working copy) @@ -184,6 +184,8 @@ PyAPI_FUNC(PyObject *) PyErr_Format(PyObject *, const char *, ...); +PyAPI_FUNC(PyObject *) PyErr_AsUnicode(void); + #ifdef MS_WINDOWS PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithFilenameObject( int, const char *); Index: Doc/c-api/exceptions.rst =================================================================== --- Doc/c-api/exceptions.rst (revision 73446) +++ Doc/c-api/exceptions.rst (working copy) @@ -204,6 +204,12 @@ copied as-is to the result string, and any extra arguments discarded. +.. cfunction:: PyObject* PyErr_AsUnicode() + + This function returns the output of :cfunc:`PyErr_Print` as a string. + it returns *NULL* without setting an exception if the conversion fails. + + .. cfunction:: void PyErr_SetNone(PyObject *type) This is a shorthand for ``PyErr_SetObject(type, Py_None)``.