[Python-Dev] Weird problem with exceptions raised in extension module

Guido van Rossum guido@python.org
Thu, 20 Jun 2002 13:45:18 -0400


> I'm getting strange behaviour when raising an
> exception in a extension module generated by
> Pyrex. The extension module does the equivalent of
> 
>   def foo():
>     raise TypeError("Test-Exception")
> 
> If I invoke it with the following Python code:
> 
>   try:
>     mymodule.foo()
>   except IOError:
>     print "blarg"
> 
> the following happens:
> 
>   Traceback (most recent call last):
>     File "<stdin>", line 3, in ?
>   SystemError: 'finally' pops bad exception
> 
> This only happens when the try-except catches
> something *other* than the exception being raised.
> If the exception being raised is caught, or
> no exception catching is done, the exception
> is handled properly.
> 
> Also, it only happens when an *intance* is used
> as the exception object. If I do this instead:
> 
>   raise TypeError, "Test-Exception"
> 
> the problem doesn't occur.
> 
> The relevant piece of C code generated by
> Pyrex is as follows. Can anyone see if I'm
> doing anything wrong? (I'm aware that there's
> a missing Py_DECREF, but it shouldn't be
> causing this sort of thing.)
> 
> The Python version I'm using is 2.2.
> 
>   __pyx_1 = __Pyx_GetName(__pyx_b, "TypeError"); 
>   if (!__pyx_1) goto __pyx_L1;
>   __pyx_2 = PyString_FromString(__pyx_k1); 
>   if (!__pyx_2) goto __pyx_L1;
>   __pyx_3 = PyTuple_New(1); 
>   if (!__pyx_3) goto __pyx_L1;
>   PyTuple_SET_ITEM(__pyx_3, 0, __pyx_2);
>   __pyx_2 = 0;
>   __pyx_4 = PyObject_CallObject(__pyx_1, __pyx_3); 
>   if (!__pyx_4) goto __pyx_L1;
>   Py_DECREF(__pyx_3); 
>   __pyx_3 = 0;
>   PyErr_SetNone(__pyx_4);
>   Py_DECREF(__pyx_4); 
>   __pyx_4 = 0;
>   goto __pyx_L1;
> 
>   /*...*/

It seems that this is just for

   raise TypeError, "Test-Exception"

Shouldn't you show the code for the try/except and for the function
call/return too?

But I think that you shouldn't be calling PyErr_SetNone() here -- I
think you should call PyErr_SetObject(__pyx_1, __pyx_2).

For details see do_raise() in ceval.c.

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