[Cython] [cython-users] Re: How to find out where an AttributeError is ignored

Stefan Behnel stefan_ml at behnel.de
Fri Jan 27 17:58:10 CET 2012


mark florisson, 27.01.2012 17:30:
> On 27 January 2012 16:22, mark florisson <markflorisson88 at gmail.com> wrote:
>> On 27 January 2012 15:47, Simon King <simon.king at uni-jena.de> wrote:
>>> Hi all,
>>>
>>> I am still *very* frustrated about the fact that Cython does not tell
>>> where the error occurs. Since about one week, I am adding lots and
>>> lots of lines into Sage that write a log into some file, so that I get
>>> at least some idea where the error occurs. But still: Even these
>>> extensive logs do not provide a hint on what exactly is happening.
>>>
>>> How can I patch Cython such that some more information on the location
>>> of the error is printed? I unpacked Sage's Cython spkg, and did "grep -
>>> R ignored .", but the code lines containing the word "ignored" did not
>>> seem to be the lines that are responsible for printing the warning
>>> message
>>>   Exception AttributeError: 'PolynomialRing_field_with_category'
>>> object has no attribute '_modulus' in  ignored
>>>
>>> Can you point me to the file in Sage's Cython spkg which is
>>> responsible for printing the warning?
>>>
>>> Best regards,
>>> Simon
>>
>> These messages are written by PyErr_WriteUnraisable, which is a
>> CPython C API function that writes unraisable exceptions. There are
>> typically two reasons for unraisable exceptions:
>>
>>    1) as Robert mentioned, a function that does not allow propagation
>> of exceptions, e.g.
>>
>>        cdef int func():
>>            raise Exception
>>
>>        Here there is no way to propagate the raised exception, so
>> instead one should write something like
>>
>>            cdef int func() except -1: ...
>>
>>        Alternatively one may use 'except *' in case there is no error
>> indicator and Cython should always check, or "except ? -1" which means
>> "-1 may or may not indicate an error".
>>
>>    2) in deallocators or finalizers (e.g. __dealloc__ or __del__)
>>
>> For functions the right thing is to add an except clause, for
>> finalizers and destructors one could use the traceback module, e.g.
>>
>>    try:
>>        ...
>>    except:
>>        traceback.print_exc()
>>
>> If this all still doesn't help, try setting a (deferred) breakpoint on
>> __Pyx_WriteUnraisable or PyErr_WriteUnraisable.
> 
> Actually, I don't see why the default is to write unraisable
> exceptions. Instead Cython could detect that exceptions may propagate
> and have callers do the check (i.e. make it implicitly "except *").
> Was this not implemented because Cython only knows whether functions
> may propagate exceptions at code generation time by looking at the
> presence of an error label?
> Maybe it could keep code insertion points around for every call to
> such a potential function and if the function uses the error label
> have the caller perform the check? Although I do forsee problems for
> external such functions... maybe Cython could have it's own
> threadstate regardless of the GIL which would indicate whether an
> error has occurred? e.g. CyErr_Occurred()?

Yep, those are the kind of reasons why writing unraisable exceptions is the
default.

Stefan


More information about the cython-devel mailing list