On Tue, Jan 31, 2012 at 8:30 AM, mark florisson <markflorisso...@gmail.com> wrote: > On 31 January 2012 02:12, Robert Bradshaw <rober...@math.washington.edu> > wrote: >> On Fri, Jan 27, 2012 at 1:01 PM, Stefan Behnel <stefan...@behnel.de> wrote: >>> Dag Sverre Seljebotn, 27.01.2012 21:03: >>>> On 01/27/2012 05:58 PM, Stefan Behnel wrote: >>>>> mark florisson, 27.01.2012 17:30: >>>>>> On 27 January 2012 16:22, mark florisson<markflorisso...@gmail.com> >>>>>> wrote: >>>>>>> On 27 January 2012 15:47, Simon King<simon.k...@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 *"). >>>> >>>> As for speed, there's optimizations on this, e.g., "except? 32434623" if >>>> the return type is int, "except? 0xfffff..." if the return type is a >>>> pointer. >>>> >>>> And for floating point, we could make our own NaN -- that's obscure enough >>>> that it could probably be made "except cython.cython_exception_nan" by >>>> default, not "except? cython.cython_exception_nan". >>> >>> The problem with that is that we can't be sure that Cython will be the only >>> caller. So exceptions may still not propagate in cases, and users will have >>> to know about these "obscure" values and that they must deal with them >>> manually then. >>> >>> You could add that we'd just have to disable this when user code takes a >>> pointer from a function, but then, how many rules are there that users will >>> have to learn and remember after such a change? And what's that for a >>> language that changes the calling semantics of a function because way down >>> in the code someone happens to take a pointer to it? >>> >>> >>>>>> 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. >>>> >>>> Still, >>> >>> I wasn't really advocating this behaviour, just indicating that it's hard >>> to do "better", because this "better" isn't all that clear. It's also not >>> "better" for all code, which means that we get from one trade-off to >>> another, while breaking existing code at the same time. Not exactly >>> paradise on either side of the tunnel. >> >> I still feel like we're stuck in the wrong default. I'd rather require >> more work to interact with C libraries than require more work to >> convert innocent-looking Python to Cython. >> >>> One example that keeps popping up in my mind is callback functions that >>> cannot propagate errors, at least not the CPython way. I have a couple of >>> those in lxml, even some returning void. So I wrap their code in a bare >>> try-except and when an exception strikes, I set a C error flag to tell the >>> C library that something went wrong and return normally. No Python code >>> outside of the try block. But Cython still generates code for unraisable >>> errors. Why? Because the internal code that handles the bare except clause >>> may fail and raise an exception. How about that? >>> >>> >>>> the need to explicitly declare "except *" keeps coming up again and >>>> again, and is really a blemish on the usability of Cython. When teaching >>>> people Cython, then it's really irritating to have to follow "all you need >>>> to do is add some 'cdef' and some types" with "and then you need to >>>> remember to say "except *", or you're in deep trouble". Cython sort of >>>> looks very elegant until that point... >>> >>> I know what this feels like. The problem is that these things *are* complex. >> >> Yes. We've been wrestling with this issue almost since Cython's inception... >> >> I like Mark's two-function idea, with the caveat that f(bad_argument) >> now behaves quite differently than (&f)[0](bad_argument) for even more >> obscure reasons. But it may be the way to go. >> >> The other option is to embed the error behavior into the signature and >> require casts to explicitly go from one to the other. This would >> probably require a notation for never raising an exception (e.g. >> "except -"). Cdef public or api functions could require an except >> declaration (positive or negative), ordinary cdef functions would be >> "except *" by default, and cdef extern functions would be "except -" >> by default. > > Only except * and except ? have ever made some sense to me. Except + > is the most mysterious syntax ever, imho it should have been 'except > cpperror' or something. And when you try to search for "except +" or > "except *" etc on docs.cython.org it doesn't find anything, which > makes it hard for people reading the code and unfamiliar with the > syntax to figure out what it means. In general I also think decorators > would have been clearer when defining such functions. Let's please not > introduce more weird syntax.
"except IDENTIFIER" already has a meaning, and it's nice to have as few keywords as possible (though I agree for searching). The problem with decorators is that they don't lend themselves being declarable part of a type declaration. What would the syntax be for a function pointer (or extern function) that does propagate Python exceptions? What about one that throws a C++ exception? > In any event I don't see why we'd want 'except -', as we're trying to > get rid of the except clause. Is it possible to get rid of it entirely? I was thinking we could provide more natural defaults, but the user might still need to declare when things are different. > So you can still get your old behaviour > for function pointers by not using the except clause and having it > write unraisable exceptions in the function, but in Cython space you'd > simply get better semantics (that is, propagating exceptions). I agree with Dag that this is very similar to the GIL issue, and should probably be tackled similarly. - Robert _______________________________________________ cython-devel mailing list cython-devel@python.org http://mail.python.org/mailman/listinfo/cython-devel