classification
Title: C/API PyErr_AsUnicode()
Type: enhancement Stage: patch review
Components: Interpreter Core Versions: Python 3.4
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: Trundle, amaury.forgeotdarc, ideasman42, vstinner
Priority: normal Keywords: patch

Created on 2009-06-14 17:03 by ideasman42, last changed 2013-07-06 00:36 by christian.heimes.

Files
File name Uploaded Description Edit
PyErr_AsUnicode_r73429.diff ideasman42, 2009-06-14 17:12 updated patch
PyErr_AsUnicode_r73443.diff ideasman42, 2009-06-16 12:22 patch that wont override sys.stderr as advaised.
Messages (8)
msg89357 - (view) Author: Campbell Barton (ideasman42) * Date: 2009-06-14 17:03
This function returns the output of PyErr_Print as a unicode string.

We needed this in Blender3D because it has its own error logging system
which does not use the console.

The patch is made against python3k r73429.
msg89358 - (view) Author: Campbell Barton (ideasman42) * Date: 2009-06-14 17:08
last patch was bad heres a new one.
msg89372 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2009-06-14 22:21
PyErr_Print seems a too high-level function for this usage:
- it uses sys.excepthook
- it exits the process if the exception is SystemExit (!)

I'd prefer a function similar to PyErr_Display. And sys.stderr should 
not be redirected to a temporary stream: this change is not thread safe.
For example, A new function PyErr_DisplayEx could take an additional 
(PyObject *fp) argument.

As for the Blender use case: isn't it appropriate for Blender to change 
sys.stderr globally, since the console is not used?
msg89429 - (view) Author: Campbell Barton (ideasman42) * Date: 2009-06-16 11:57
Thanks for the feedback, I wasnt aware of PyErr_Display, its not
documented as far as I know.

http://docs.python.org/dev/py3k/genindex-all.html

For blender, its development id still in progress so we don't yet have
an internal console replacement.

however we use a number of python apis in blender (game engine api, UI
api, wrapping our own data) - So there are a number of places where this
function could come in handy, and completely replacing the stdout isn't
always an option - when running the game engine for instance.

Ill look into using a PyErr_DisplayEx
msg89430 - (view) Author: Campbell Barton (ideasman42) * Date: 2009-06-16 12:22
Updated with an PyErr_DisplayEx function that accepts a file argument.
msg125723 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2011-01-07 22:40
+	PyErr_Fetch(&error_type, &error_value, &error_traceback);
+	
+	PyErr_Clear();

I think that the call to PyErr_Clear() is useless, PyErr_Fetch() already cleared the exception.

+	/* clear the error */
+	PyErr_Restore(error_type, error_value, error_traceback);
+	PyErr_Clear();

Why do you restore the error if you clear it directly? I think that at this position, there is no current exception. So it may be simplified as:

Py_DECREF(error_type);
Py_DECREF(error_value);
Py_DECREF(error_traceback);

I suppose here that all these 3 variables are not NULL.

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

Minor style remark: you can remove the "else" keywords here.

You should factorize the error handling at the end using "goto error;" with a error handler looking like:
------------
   ...
   goto finally;

error:
   PyErr_Clear();
   Py_CLEAR(stringio_buf);
finally:
   Py_XDECREF(string_io_mod);
   Py_XDECREF(string_io);
   Py_XDECREF(string_io_getvalue);
   return NULL;
------------
In my opinion, it's easier to maintain it, and more readable.
msg125724 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2011-01-07 22:45
/* Returns the exception string as a new
   PyUnicode object or NULL if the conversion failed */

NULL is not very useful to analyze the error :-/ Why don't keep errors if the conversion failed? The caller will be responsible to use the new error, or to clear it.

If PyErr_AsUnicode() raises a new error on conversion error, you should raise an error on:

+	if (!PyErr_Occurred())
+		return NULL;

On keep PyImport_ImportModule(), PyObject_CallMethod() and PyObject_GetAttrString() error.

Oh, by the way, PyErr_AsUnicode returns NULL and raise an error if PyObject_CallObject() failed (if StringIO().getvalue() failed).
msg125726 - (view) Author: Andreas Stührk (Trundle) * Date: 2011-01-07 23:12
There should also be a call to `PyErr_NormalizeException()`, as `PyErr_Fetch()` can return unnormalized exceptions (see e.g. issue #10756).
History
Date User Action Args
2013-07-06 00:36:07christian.heimessetcomponents: + Interpreter Core, - None
versions: + Python 3.4, - Python 3.3
2011-01-07 23:12:48Trundlesetnosy: + Trundle
messages: + msg125726
2011-01-07 22:45:04vstinnersetmessages: + msg125724
2011-01-07 22:40:37vstinnersetmessages: + msg125723
2011-01-06 16:59:33pitrousetnosy: + vstinner
stage: patch review
type: enhancement

versions: + Python 3.3, - Python 3.1
2009-06-16 12:22:47ideasman42setfiles: + PyErr_AsUnicode_r73443.diff

messages: + msg89430
2009-06-16 11:57:12ideasman42setmessages: + msg89429
2009-06-14 22:21:54amaury.forgeotdarcsetnosy: + amaury.forgeotdarc
messages: + msg89372
2009-06-14 17:12:27ideasman42setfiles: + PyErr_AsUnicode_r73429.diff
2009-06-14 17:12:12ideasman42setfiles: - PyErr_AsUnicode_r73429.diff
2009-06-14 17:09:04ideasman42setfiles: - PyErr_AsUnicode_r73429.diff
2009-06-14 17:08:52ideasman42setfiles: + PyErr_AsUnicode_r73429.diff

messages: + msg89358
2009-06-14 17:03:37ideasman42create