Re: [Python-Dev] PEP 344: Exception Chaining and Embedded Tracebacks
Ka-Ping Yee wrote: [...] (a) ban string exceptions (b) require all exceptions to derive from Exception (c) ban bare except: (d) eliminate sys.exc_* I think somewhere in this list should be: (?) Remove string exceptions from the Python stdlib and perhaps: (?) Make Exception a new style class Bye, Walter Dörwald ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 344: Exception Chaining and Embedded Tracebacks
Michael Hudson wrote: Walter Dörwald [EMAIL PROTECTED] writes: Ka-Ping Yee wrote: [...] (a) ban string exceptions (b) require all exceptions to derive from Exception (c) ban bare except: (d) eliminate sys.exc_* I think somewhere in this list should be: (?) Remove string exceptions from the Python stdlib I think this is done, more or less. There's one in test_descr, I think (probably testing that you can't raise str-subclasses but can raise strs). There are a few appearances in docstrings, and the Demo, Mac/Tools and Tools directories. Those should be rather simple to fix. The only problem might be if there is code that catches these exceptions. and perhaps: (?) Make Exception a new style class I have a patch for this on SF, of course. http://www.python.org/sf/1104669 it seems. Bye, Walter Dörwald ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 344: Exception Chaining and Embedded Tracebacks
[Guido] Here's a bunch of commentary: [Ping] Thanks. Sorry it's taken me a couple of days to get back to this. I think i'm caught up on the mail now. No problem! snip Also, in that same example, according to your specs, the TypeError raised by bar() has the ZeroDivisionError raised in foo() as its context. Do we really want this? I don't think it's absolutely necessary, though it doesn't seem to hurt. We agree that if the TypeError makes it up to foo's frame, it should have the ZeroDivisionError as its __context__, right? Yes. If so, do i understand correctly that you want the __context__ to depend on where the exception is caught as well as where it is raised? I think so, but that's not how I think about it. IMO the only time when the context becomes *relevant* is when a finally/except clause is left with a different exception than it was entered. In your thinking, is this mainly a performance or a cleanliness issue? Hard to say; the two are often difficult to separate for me. The performance in this case bothers me because it means unnecessary churn when exceptions are raised and caught. I know I've said in the past I don't care about the performance of exceptions, but that's not *quite* true, given that they are quite frequently used for control flow (e.g. StopIteration). I don't know how to quantify the performance effect though (unless it means that exceptions would have to be *instantiated* sooner than currently; in those cases where exception instantiation is put off, it is put off for one reason, and that reason is performance! The cleanliness issue is also important to me: when I have some isolated code that raises and successfully catches an exception, and that code happens to be used by a logging operation that is invoked from an exception handler, why would the context of the exception have to include something that happened way deeper on the stack and that is totally irrelevant to the code that catches *my* exception? Basically i was looking for the simplest description that would guarantee ending up with all the relevant tracebacks reported in chronological order. I thought it would be more complicated if we had to keep modifying the traceback on the way up, but now that i've re-learned how tracebacks are constructed, it's moot -- we're already extending the traceback on the way through each frame. I have a proposal for the implicit chaining semantics that i'll post in a separate message so it isn't buried in the middle of this one. OK, looking forward to it. Do we really need new syntax to set __cause__? Java does this without syntax by having a standard API initCause() (as well as constructors taking a cause as argument; I understand why you don't want to rely on that -- neither does Java). That seems more general because it can be used outside the context of a raise statement. I went back and forth on this. An earlier version of the PEP actually proposes a 'setcause' method. I eventually settled on a few reasons for the raise ... from syntax: 1. (major) No possibility of method override; no susceptibility to manipulation of __dict__ or __getattr__; no possibility of another exception happening while trying to set the cause. Hm; the inability to override the method actually sounds like a major disadvantage. I'm not sure what you mean with __dict__ or __getattr__ except other ways to tweak the attribute assignment; maybe you forgot about descriptors? Another exception could *still* happen and I think the __context__ setting mechanism will take care of it just fine. 2. (moderate) There is a clear, distinct idiom for exception replacement requiring that the cause and effect must be identified together at the point of raising. Well, nothing stops me from adding a setCause() method to my own exception class and using that instead of the from syntax, right? I'm not sure why it is so important to have a distinct idiom, and even if we do, I think that a method call will do just fine: except EnvironmentError, err: raise MyApplicationError(boo hoo).setCause(err) 3. (minor) No method namespace pollution. 4. (minor) Less typing, less punctuation. The main thing is that handling exceptions is a delicate matter, so it's nice to have guarantees that the things you're doing aren't going to suddenly raise more exceptions. I don't see that there's all that much that can go wrong in setCause(). After all, it's the setCause() of the *new* exception (which you can know and trust) that could cause trouble; a boobytrap in the exception you just caught could not possibly be set off by simply using it as a cause. (It can cause the traceback printing to fail, of course, but that's not a new issue.) Why insert a blank line between chained tracebacks? Just to make them easier to read. The last line of each traceback is important because it identifies the
Re: [Python-Dev] PEP 344: Exception Chaining and Embedded Tracebacks
On Monday 16 May 2005 22:41, Ka-Ping Yee wrote: http://www.python.org/peps/pep-0344.html | 2. Whenever an exception is raised, if the exception instance does | not already have a '__context__' attribute, the interpreter sets | it equal to the thread's exception context. Should that be if the exception instance does not already have a __context__ attribute or the value of that attribute is None -- Toby Dickenson ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 344: Exception Chaining and Embedded Tracebacks
Here's another rule-of-thumb: when the VM and the user *share* the attribute space of an object, the VM uses system attributes; the VM uses plain attributes for objects that it owns completely (like code objects, frames and so on, which rarely figure user code except for the explicit purpose of introspection). So I think the PEP should continue to use __traceback__ etc. On 5/17/05, Greg Ewing [EMAIL PROTECTED] wrote: Guido van Rossum wrote: Unfortunately I can't quite decide whether either rule applies in the case of exceptions. I think you'd at least be justified in using the magic rule, since they're set by the exception machinery. -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 344: Exception Chaining and Embedded Tracebacks
On Mon, May 16, 2005, Guido van Rossum wrote: My rule has more to do with who owns the namespace on the one hand, and with magic behavior caused (or indicated) by the presence of the attribute on the other. Class or instance is irrelevant; that most magic attributes live on classes or modules is just because those are places where most of the magic is concentrated. __init__ in a class is a system attribute because it has a magic meaning (invoked automatically on instantiation). __file__ and __name__ in a module (and __module__ and __name__ in a class!) are system attributes because they are imposing on the user's use of the namespace. (Note: next was a mistake; it should have been __next__ because of the magic rule.) From my POV, part of the reasoning should be the extent to which the attribute is intended to be publicly accessible -- part of the primary documented interface. __init__ is magic, fine. But __name__ isn't part of the primary use for a class, whereas these new exception attributes will be part of the public interface for exceptions, just like the methods for the Queue class. (I'm using Queue in specific because it's intended to be subclassed.) -- Aahz ([EMAIL PROTECTED]) * http://www.pythoncraft.com/ And if that makes me an elitist...I couldn't be happier. --JMS ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 344: Exception Chaining and Embedded Tracebacks
[Guido van Rossum] My rule has more to do with who owns the namespace on the one hand, and with magic behavior caused (or indicated) by the presence of the attribute on the other. Class or instance is irrelevant; that most magic attributes live on classes or modules is just because those are places where most of the magic is concentrated. __init__ in a class is a system attribute because it has a magic meaning (invoked automatically on instantiation). __file__ and __name__ in a module (and __module__ and __name__ in a class!) are system attributes because they are imposing on the user's use of the namespace. (Note: next was a mistake; it should have been __next__ because of the magic rule.) [Aahz] From my POV, part of the reasoning should be the extent to which the attribute is intended to be publicly accessible -- part of the primary documented interface. __init__ is magic, fine. But __name__ isn't part of the primary use for a class, whereas these new exception attributes will be part of the public interface for exceptions, just like the methods for the Queue class. (I'm using Queue in specific because it's intended to be subclassed.) I dunno. Would you find __doc__ not part of the primary, documented interface of classes? Or __bases__? The Queue class is irrelevant because the VM doesn't know about it; *almost* all system atribute are referenced by the VM (or by the compiler) at some point(*). The reverse is not true, BTW -- many built-in objects (e.g. tracebacks, code and function objects) have non-system attributes. If this were Python 3000, I'd definitely make the traceback and cause non-system attributes. Given we're retrofitting, I'm less sure; surely some user-defined exceptions have cause and/or traceback attributes already. (*) I'd say metadata like __version__ is the exception; it's a system attribute because it's metadata, and because it lives in a crowded namespace, and because it was retrofitted as a convention. -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 344: Exception Chaining and Embedded Tracebacks
I figured out the semantics that I'd like to see intuitively for setting the context. I'm not saying this is all that reasonable, but I'd like throw it out anyway to see what responses it gets. Consider try: BLOCK except EXCEPTION, VAR: HANDLER I'd like to see this translated into try: BLOCK except EXCEPTION, VAR: __context = VAR try: HANDLER except Exception, __error: __error.__context__ = __context raise i.e. the context is set only upon *leaving* the handler. (The translation for finally is hairier but you get the idea at this point.) My intuition prefers this over Ping's solution because HANDLER could easily invoke code that (after many stack levels deep) raises and catches many exceptions, and I'd hate to see all those be bothered by the context (far down on the stack) that is irrelevant. BTW, please study how the traceback is built up. I believe that if we store the traceback in the exception instance, we have to update the __traceback__ attribute each time we pop a stack level. IIRC that's how the traceback chain is built up. (The alternative, building the whole chain when the exception is raised, would be too expensive for exceptions raised *and* caught somewhere deep.) -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 344: Exception Chaining and Embedded Tracebacks
Guido van Rossum wrote: Consider try: BLOCK except EXCEPTION, VAR: HANDLER I'd like to see this translated into try: BLOCK except EXCEPTION, VAR: __context = VAR try: HANDLER except Exception, __error: __error.__context__ = __context raise If I interpret the above translation correctly, then: try: BLOCK1 except EXCEPTION1, VAR1: try: BLOCK2 except EXCEPTION2, VAR2: HANDLER with exceptions occuring in BLOCK1, BLOCK2 and HANDLER would result in HANDLER's exception with __context__ set to BLOCK1's exception and BLOCK2's exception would be lost. --eric ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 344: Exception Chaining and Embedded Tracebacks
Guido van Rossum wrote: Unfortunately I can't quite decide whether either rule applies in the case of exceptions. I think you'd at least be justified in using the magic rule, since they're set by the exception machinery. Greg ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 344: Exception Chaining and Embedded Tracebacks
On Mon, May 16, 2005, Ka-Ping Yee wrote: This PEP is a concrete proposal for exception chaining, to follow up on its mention here on Python-Dev last week as well as earlier discussions in the past year or two. http://www.python.org/peps/pep-0344.html I've tried to summarize the applications for chaining mentioned in these discussions, survey what's available in other languages, and come up with a precise specification. PEP 344 proposes three standard attributes on traceback objects: __context__ for implicit chaining (an unexpected exception occurred during 'except' or 'finally' processing) __cause__ for explicit chaining (intentional translation or augmenting of exceptions, set by raise EXC from CAUSE) __traceback__ to point to the traceback Hope this is useful. I'd like your feedback. Thanks! I'll comment here in hopes of staving off responses from multiple people: I don't think these should be double-underscore attributes. The currently undocumented ``args`` attribute isn't double-underscore, and I think that's precedent to be followed. -- Aahz ([EMAIL PROTECTED]) * http://www.pythoncraft.com/ And if that makes me an elitist...I couldn't be happier. --JMS ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 344: Exception Chaining and Embedded Tracebacks
[Ka-Ping Yee] This PEP is a concrete proposal for exception chaining, to follow up on its mention here on Python-Dev last week as well as earlier discussions in the past year or two. http://www.python.org/peps/pep-0344.html Here's a bunch of commentary: You're not giving enough credit to Java, which has the cause part nailed IMO. I like the motivation and rationale, but I think the spec is weak and would benefit from a better understanding of how exception handling currently works. In particular, please read and understand the comment in ceval.c starting with this line: /* Implementation notes for set_exc_info() and reset_exc_info(): There's too much text devoted early on to examples. I think these should come at the end; in particular, hiding the proposed semantics at the very end of a section that otherwise contains only illustrative examples is a bad idea (especially since the examples are easy enough to guess, if you've read the rationale). I don't think the PEP adequately predicts what should happen in this example: def foo(): try: 1/0 # raises ZeroDivisionError except: bar() raise sys.does_not_exist # raises AttributeError def bar(): try: 1+ # raises TypeError except TypeError: pass Intuitively, the AttributeError should have the ZeroDivisionError as its __context__, but I think the clearing of the thread's exception context when the except clause in bar() is left will drop the exception context. If you follow the save/restore semantics described in that ceval.c comment referenced above, you'll get the correct semantics, I believe. Also, in that same example, according to your specs, the TypeError raised by bar() has the ZeroDivisionError raised in foo() as its context. Do we really want this? I still have the feeling that perhaps the context ought to be attached later, e.g. only when an exception passes through a frame that happens to be handling an exception already (whether in an except clause or in a finally clause). When chaining exceptions, I think it should be an error if the cause is not an exception instance (or None). Yes, this will just substitute a different exception, but I still think it's the right thing to do -- otherwise code walking the chain of causes must be constantly aware of this possibility, and since during normal use it will never happen, that would be a great way to trip it up (perhaps even to cause a circularity!). Do we really need both __context__ and __cause__? Methinks that you only ever need one: either you explicitly chain a new exception to a cause, and then the context is probably the same or irrelevant, or you don't explicitly chain, and then cause is absent. Since the traceback printing code is to prefer __cause__ over __context__, why can't we unify these? About the only reason I can think of is that with __cause__ you know it was intentional and with __context__ you know it wasn't; but when is it important knowing the difference? Do we really need new syntax to set __cause__? Java does this without syntax by having a standard API initCause() (as well as constructors taking a cause as argument; I understand why you don't want to rely on that -- neither does Java). That seems more general because it can be used outside the context of a raise statement. Why insert a blank line between chained tracebacks? In Java, I often find the way chained tracebacks are printed confusing, because the deepest stack frame (where the exception originally occurred) is no longer at the top of the printout. I expect the same confusion to happen for Python, since it prints everything in the exact opposite order as Java does, so again the original exception is somewhere in the middle. I don't think I want to fix this by printing the outermost exception first and the chained exception later (which would keep the stack frames in their proper order but emphasizes the low-level exception rather than the one that matches the except clause that would have caught it at the outermost level), but I might want to add an extra line at the very end (and perhaps at each chaining point) warning the user that the exception has a chained counterpart that was printed earlier. Why should the C level APIs not automatically set __context__? (There may be an obvious reason but it doesn't hurt stating it.) You're unclear on how the C code should be modified to ensure that the proper calls to PyErr_SetContext() are made. I was surprised to learn that yield clears the exception state; I wonder if this isn't a bug in the generator implementation? IMO better semantics would be for the exception state to survive across yield. You should at least mention what should happen to string exceptions, even if (as I presume) the only sane approach is not to support this for string exceptions (a string exception may be the end of the chain, but it cannot have a chained
Re: [Python-Dev] PEP 344: Exception Chaining and Embedded Tracebacks
Guido van Rossum wrote: [SNIP - bunch of points from Guido] Do we really need both __context__ and __cause__? Methinks that you only ever need one: either you explicitly chain a new exception to a cause, and then the context is probably the same or irrelevant, or you don't explicitly chain, and then cause is absent. Since the traceback printing code is to prefer __cause__ over __context__, why can't we unify these? About the only reason I can think of is that with __cause__ you know it was intentional and with __context__ you know it wasn't; but when is it important knowing the difference? I am with Guido. I don't think the need to know if an exception was chained explicitly or implicitly will be important enough to warrant a separate attribute. And if people care that much that can tack on a random attribute like explicit_chain or something to the exception on their own. [SNIP] In Java, I often find the way chained tracebacks are printed confusing, because the deepest stack frame (where the exception originally occurred) is no longer at the top of the printout. I expect the same confusion to happen for Python, since it prints everything in the exact opposite order as Java does, so again the original exception is somewhere in the middle. I don't think I want to fix this by printing the outermost exception first and the chained exception later (which would keep the stack frames in their proper order but emphasizes the low-level exception rather than the one that matches the except clause that would have caught it at the outermost level), but I might want to add an extra line at the very end (and perhaps at each chaining point) warning the user that the exception has a chained counterpart that was printed earlier. Just a simple [chained exception] note or something? Sounds good. [SNIP] You should probably reference the proposal (pending a PEP; I think Brett is working on it?) My plan is to write the Exceptions in Python 3000 PEP shortly after I start my internship. Going to put that at a higher priority than the AST branch to make sure I get to it some time before I leave the country. =) -Brett ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 344: Exception Chaining and Embedded Tracebacks
On Mon, May 16, 2005 at 08:09:54PM -0500, Ka-Ping Yee wrote: On Mon, 16 May 2005, Aahz wrote: I'll comment here in hopes of staving off responses from multiple people: I don't think these should be double-underscore attributes. The currently undocumented ``args`` attribute isn't double-underscore, and I think that's precedent to be followed. That isn't the criterion i'm using, though. Here's my criterion, and maybe then we can talk about what the right criterion should be: System attributes are for protocols defined by the language. (I'm using the term system attribute here to mean an attribute with a double-underscore name, which i picked up from something Guido wrote a while back [1].) For example, __init__, __add__, __file__, __name__, etc. are all attributes whose meaning is defined by the language itself as opposed to the Python library. A good indicator of this is the fact that their names are hardcoded into the Python VM. I reasoned that __cause__, __context__, and __traceback__ should also be system attributes since their meaning is defined by Python. Exceptions are just classes; they're intended to be extended in arbitrary application-specific ways. It seemed a good idea to leave that namespace open. I prefer trichomomies over dichotomies, but whether single or double underscores are the bad or the ugly I'll leave to others. In python double underscores can only mean I don't handle this, my class does or I'm a C++ weenie, can I pretend this is private? Excluding the private non-argument the only question is where it goes in the class hierarchy. Is it a property you would normally associate with the instance, the class of an instance, or the class of a class (type). To me it feels like a property of the instance. The values are never shared by expections of the class so just make it a plain variable to remind other people of that too. -jackdied ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 344: Exception Chaining and Embedded Tracebacks
[Jack Diederich] I prefer trichomomies over dichotomies, but whether single or double underscores are the bad or the ugly I'll leave to others. In python double underscores can only mean I don't handle this, my class does or I'm a C++ weenie, can I pretend this is private? Excluding the private non-argument the only question is where it goes in the class hierarchy. Is it a property you would normally associate with the instance, the class of an instance, or the class of a class (type). To me it feels like a property of the instance. The values are never shared by expections of the class so just make it a plain variable to remind other people of that too. Can't tell if you're just trying to be funny, but that sounds like nothing remotely like the rule I use in my head to decide whether to make something a system attribute or a regular attribute. My rule has more to do with who owns the namespace on the one hand, and with magic behavior caused (or indicated) by the presence of the attribute on the other. Class or instance is irrelevant; that most magic attributes live on classes or modules is just because those are places where most of the magic is concentrated. __init__ in a class is a system attribute because it has a magic meaning (invoked automatically on instantiation). __file__ and __name__ in a module (and __module__ and __name__ in a class!) are system attributes because they are imposing on the user's use of the namespace. (Note: next was a mistake; it should have been __next__ because of the magic rule.) Unfortunately I can't quite decide whether either rule applies in the case of exceptions. I think it's totally plausible to say all exceptions derive from Throwable, which predefines the following attributes: traceback, cause. OTOH making them system attributes is more backwards compatible. -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com