How to catch a usefull error message ?

Chris Angelico rosuav at gmail.com
Thu Apr 25 02:25:32 EDT 2019


On Thu, Apr 25, 2019 at 2:32 PM Vincent Vande Vyvre
<vincent.vande.vyvre at telenet.be> wrote:
>
> Le 24/04/19 à 19:57, MRAB a écrit :
> > On 2019-04-23 20:21, Vincent Vande Vyvre wrote:
> >> Le 23/04/19 à 20:54, Chris Angelico a écrit :
> >>> On Wed, Apr 24, 2019 at 4:47 AM Vincent Vande Vyvre
> >>> <vincent.vande.vyvre at telenet.be> wrote:
> >>>
> >>> Into the lib:
> >>>
> >>> static int
> >>> ImgProc_init(ImgProc *self, PyObject *args, PyObject *kwds)
> >>> {
> >>>       PyObject *tmp;
> >>>       char *fname;
> >>>
> >>>       if (!PyArg_ParseTuple(args, "s", &fname))
> >>>           return NULL;
> >>>
> >>>       tmp = self->src;
> >>>       self->src = PyUnicode_FromString(fname);
> >>>       Py_XDECREF(tmp);
> >>>       return 0;
> >>> }
> >>>
> >>> If i do:
> >>>       try:
> >>>           tif = ImgProc(123)
> >>>       except Exception as why:
> >>>           print(sys.exc_info())
> >>>           raise
> >>> I get:
> >>> (<class 'SystemError'>, SystemError("<class '_liboqapy.ImgProc'>
> >>> returned a result with an error set",), <traceback object at
> >>> 0x7f3bcac748c8>)
> >>> TypeError: argument 1 must be str, not int
> >>>
> >>> The above exception was the direct cause of the following exception:
> >>>
> >>> Traceback (most recent call last):
> >>>     File "/home/vincent/oqapy-3/trunk/filters/ui_lenscorrection.py",
> >>> line
> >>> 104, in on_main_cursor_changed
> >>>       self.prepare_preview_process()
> >>>     File "/home/vincent/oqapy-3/trunk/filters/ui_lenscorrection.py",
> >>> line
> >>> 137, in prepare_preview_process
> >>>       self.main.process_on_preview(params)
> >>>     File "/home/vincent/oqapy-3/trunk/filters/lenscorrection.py", line
> >>> 56, in process_on_preview
> >>>       tif = ImgProc(123)
> >>> SystemError: <class '_liboqapy.ImgProc'> returned a result with an
> >>> error set
> >>> --------------------------------------------------------------------------------
> >>>
> >>> Why a SystemError ?
> >>> The SystemError means that you're using the Python C API in a way that
> >>> doesn't make sense to the interpreter. You're leaving a marker saying
> >>> "hey, I need you to throw an exception" but then you're also returning
> >>> a value. You'll need to figure out where that's happening and exactly
> >>> what is being called. How are you setting up your class?
> >>>
> >>> ChrisA
> >>
> >> The syntaxe
> >>
> >>       if (!PyArg_ParseTuple(args, "s", &fname))
> >>            return NULL;
> >>
> >> Is the usage described in the doc [*]
> >>
> >> And without block try-except I get the good one error.
> >>
> >>
> >> [*]
> >> https://docs.python.org/3.5//extending/extending.html#back-to-the-example
> >>
> >>
> > If you look at the previous example, the function's return type is
> > "PyObject *".
> >
> > On success it returns a reference (pointer) to an object; on error it
> > returns NULL.
> >
> > Your function's return type is int.
>
> In this case yes, beause it need to return the result of the command system.
>
> But the "return 0" is a common case for an "Foo_init()"
>
> see:
> https://docs.python.org/3.5//extending/newtypes.html#adding-data-and-methods-to-the-basic-example
>
> ... And that's nothing to do with my initial question

Actually, it is a lot to do with your initial question. Notice how
there are two distinct signatures being demonstrated in the example
you linked to: those declared as returning PyObject* and those
declared as returning int. If something is meant to return an object,
then returning NULL says "hey, I set an error state, unwind the stack
and raise the exception". If it's meant to return an integer, though,
it returns -1 to give that message. See details here (second
paragraph):

https://docs.python.org/3/c-api/intro.html#exceptions

The __init__ function is defined as returning an integer:

https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_init

You're right that "return 0" is a common case; that isn't the problem.
The problem is the "return NULL", which is correct for a function that
normally returns a PyObject*, but not for one that returns an int.
That's why you're getting a SystemError - you're setting the exception
state, but then saying "hey, everything's fine, it's okay to return
None".

ChrisA


More information about the Python-list mailing list