Exception Reorg PEP revised yet again
version 1.7 scales the proposal back once more (http://www.python.org/peps/pep-0348.html). At this point the only changes to the hierarchy are the addition of BaseException and TerminatingException, and the change of inheritnace for KeyboardInterrupt, SystemExit, and NotImplementedError. At this point I don't think MAL or Raymond will have any major complaints. =) Assuming no one throws a fit over this version, discussing transition is the next step. I think the transition plan is fine, but if anyone has any specific input that would be great. I could probably stand to do a more specific timeline in terms of 2.x, 2.x+1, 3.0-1, etc., but that will have to wait for another day this week. And once that is settled I guess it is either time for pronouncement or it just sits there until Python 3.0 actually starts to come upon us. -Brett
[Brett Cannon]
At this point the only changes to the hierarchy are the addition of BaseException and TerminatingException, and the change of inheritnace for KeyboardInterrupt, SystemExit, and NotImplementedError.
TerminatingException -------------------- The rationale for adding TerminatingException needs to be developed or reconsidered. AFAICT, there hasn't been an exploration of existing code bases to determine that there is going to be even minimal use of "except TerminatingException". Are KeyboardInterrupt and SystemExit often caught together on the same line and handled in the same way? If so, isn't "except TerminatingException" less explicit, clear, and flexible than "except (KeyboardInterrupt, SystemExit)"? Do we need a second way to do it? Doesn't the new meaning of Exception already offer a better idiom: try: suite() except Exception: log_or_recover() except: handle_terminating_exceptions() else: Are there any benefits sufficient to warrant yet another new built-in? Does it also warrant violating FIBTN by introducing more structure? While I'm clear on why KeyboardInterrupt and SystemExit were moved from under Exception, it is not at all clear what problem is being solved by adding a new intermediate grouping. The PEP needs to address all of the above. Right now, it contains a definition rather than justification, research, and analysis. WindowsError ------------ This should be kept. Unlike module specific exceptions, this exception occurs in multiple places and diverse applications. It is appropriate to list as a builtin. "Too O/S specific" is not a reason for eliminating this. Looking at the codebase there does not appear to be a good substitute. Eliminating this one would break code, decrease clarity, and cause modules to grow competing variants. After the change, nothing would be better and many things would be worse. NotImplementedError ------------------- Moving this is fine. Removing unnecessary nesting is a step forward. The PEP should list that as a justification. Bare excepts defaulting to Exception ------------------------------------ After further thought, I'm not as sure about this one and whether it is workable. The code fragment above highlights the issue. In a series of except clauses, each line only matches what was not caught by a previous clause. This is a useful and basic part of the syntax. It leaves a bare except to have the role of a final catchall (much like a default in C's switch-case). If one line uses "except Exception", then a subsequence bare except should probably catch KeyboardInterrupt and SystemExit. Otherwise, there is a risk of creating optical illusion errors (code that looks like it should work but is actually broken). I'm not certain on this one, but the PEP does need to fully explore the implications and think-out the consequent usability issues.
And once that is settled I guess it is either time for pronouncement or it just sits there until Python 3.0 actually starts to come upon us.
What happened to "don't take this too seriously, I'm just trying to get the ball rolling"? This PEP or any Py3.0 PEP needs to sit a good while before pronouncement. Because 3.0 is not an active project, the PEP is unlikely to be a high priority review item by many of Python's best minds. It should not be stamped as accepted until they've had a chance to think it through. Because 3.0 is still somewhat ethereal, it is not reasonable to expect them to push aside their other work to look at this right now. The PEP needs to be kicked around on the newsgroup (naming and grouping discussions are easy and everyone will have an opinion). Also the folks with PyPy, BitTorrent, Zope, Twisted, IronPython, Jython, and such need to have a chance to have their say. Because of Py3.0's low visibility, these PEPs could easily slide through prematurely. Were the project imminent, it is likely that this PEP would have had significantly more discussion. Try not to get frustrated at these reviews. Because there was no research into existing code, working to solve known problems, evaluation of alternatives, or usability analysis, it is no surprise Sturgeon's Law would apply. Since Python has been around so long, it is also no surprise that what we have now is pretty good and that improvements won't be trivially easy to come by. Raymond
Raymond Hettinger wrote:
TerminatingException --------------------
The rationale for adding TerminatingException needs to be developed or reconsidered. AFAICT, there hasn't been an exploration of existing code bases to determine that there is going to be even minimal use of "except TerminatingException".
Are KeyboardInterrupt and SystemExit often caught together on the same line and handled in the same way?
Yes, to avoid the current overbroad inheritance of "except Exception:" by intercepting and reraising these two terminating exceptions.
If so, isn't "except TerminatingException" less explicit, clear, and flexible than "except (KeyboardInterrupt, SystemExit)"?
No, TerminatingException makes it explicit to the reader what is going on - special handling is being applied to any exceptions that indicate the interpreter is expected to exit as a result of the exception. Using "except (KeyboardInterrupt, SystemExit):" is less explicit, as it relies on the reader knowing that these two exceptions share the common characteristic that they are generally meant to terminate the Python interpreter.
Are there any benefits sufficient to warrant yet another new built-in? Does it also warrant violating FIBTN by introducing more structure? While I'm clear on why KeyboardInterrupt and SystemExit were moved from under Exception, it is not at all clear what problem is being solved by adding a new intermediate grouping.
The main benefits of TerminatingException lie in easing the transition to Py3k. After transition, "except Exception:" will already do the right thing. However, TerminatingException will still serve a useful documentational purpose, as it sums up in two words the key characteristic that caused KeyboardInterrupt and SystemExit to be moved out from underneath Exception.
Bare excepts defaulting to Exception ------------------------------------
After further thought, I'm not as sure about this one and whether it is workable. The code fragment above highlights the issue. In a series of except clauses, each line only matches what was not caught by a previous clause. This is a useful and basic part of the syntax. It leaves a bare except to have the role of a final catchall (much like a default in C's switch-case). If one line uses "except Exception", then a subsequence bare except should probably catch KeyboardInterrupt and SystemExit. Otherwise, there is a risk of creating optical illusion errors (code that looks like it should work but is actually broken). I'm not certain on this one, but the PEP does need to fully explore the implications and think-out the consequent usability issues.
I'm also concerned about this one. IMO, bare excepts in Python 3k should either not be allowed at all (use "except BaseException:" intead), or they should be synonyms for "except BaseException:". Having a bare except that doesn't actually catch everything just seems wrong - and we already have style guides that say "except Exception:" is to be generally preferred over a bare except. Consenting adults and all that. . . Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia --------------------------------------------------------------- http://boredomandlaziness.blogspot.com
On 8/8/05, Raymond Hettinger <python@rcn.com> wrote:
[Brett Cannon]
At this point the only changes to the hierarchy are the addition of BaseException and TerminatingException, and the change of inheritnace for KeyboardInterrupt, SystemExit, and NotImplementedError.
TerminatingException --------------------
The rationale for adding TerminatingException needs to be developed or reconsidered. AFAICT, there hasn't been an exploration of existing code bases to determine that there is going to be even minimal use of "except TerminatingException".
Are KeyboardInterrupt and SystemExit often caught together on the same line and handled in the same way?
The problem with existing code checking for this situation is that the situation itself is not the same as it will be if bare 'except's change:: try: ... except: ... except TerminatingException: ... has never really been possible before, but will be if the PEP goes forward.
If so, isn't "except TerminatingException" less explicit, clear, and flexible than "except (KeyboardInterrupt, SystemExit)"? Do we need a second way to do it?
But what if we add other exceptions that don't inherit from Exception that was want to typically propagate up? Having a catch-all for exceptions that a bare 'except' will skip that is more explicit than ``except BaseException`` seems reasonable to me. As Nick said in another email, it provides a more obvoius self-documentation point to catch TerminatingException than ``(KeyboardInterrupt, SystemExit)``, plus you get some future-proofing on top of it in case we add more exceptions that are not caught by a bare 'except'.
Doesn't the new meaning of Exception already offer a better idiom:
try: suite() except Exception: log_or_recover() except: handle_terminating_exceptions() else:
Are there any benefits sufficient to warrant yet another new built-in? Does it also warrant violating FIBTN by introducing more structure? While I'm clear on why KeyboardInterrupt and SystemExit were moved from under Exception, it is not at all clear what problem is being solved by adding a new intermediate grouping.
The PEP needs to address all of the above. Right now, it contains a definition rather than justification, research, and analysis.
WindowsError ------------
This should be kept. Unlike module specific exceptions, this exception occurs in multiple places and diverse applications. It is appropriate to list as a builtin.
"Too O/S specific" is not a reason for eliminating this. Looking at the codebase there does not appear to be a good substitute. Eliminating this one would break code, decrease clarity, and cause modules to grow competing variants.
I unfortunately forgot to add that the exception would be moved under os, so it would be more of a renaming than a removal. The reason I pulled it was that Guido said UnixError and MacError didn't belong, so why should WindowsError stay? Obviously there are backwards-compatibility issues with removing it, but why should we have this platform-specific thing in the built-in namespace? Nothing else is platform-specific in the language until you go into the stdlib. The language itself is supposed to be platform-agnostic, and yet here is this exception that is not meant to be used by anyone but by a specific OS. Seems like a contradiction to me.
After the change, nothing would be better and many things would be worse.
NotImplementedError ------------------- Moving this is fine. Removing unnecessary nesting is a step forward. The PEP should list that as a justification.
Yay, something uncontraversial! =)
Bare excepts defaulting to Exception ------------------------------------
After further thought, I'm not as sure about this one and whether it is workable. The code fragment above highlights the issue. In a series of except clauses, each line only matches what was not caught by a previous clause. This is a useful and basic part of the syntax. It leaves a bare except to have the role of a final catchall (much like a default in C's switch-case). If one line uses "except Exception", then a subsequence bare except should probably catch KeyboardInterrupt and SystemExit. Otherwise, there is a risk of creating optical illusion errors (code that looks like it should work but is actually broken). I'm not certain on this one, but the PEP does need to fully explore the implications and think-out the consequent usability issues.
This is Guido's thing. You will have to convince him of the change. I can flesh out the PEP to argue for which ever result he wants, but that part of the proposal is in there because Guido wanted it. I am just a PEP lackey in this case. =)
And once that is settled I guess it is either time for pronouncement or it just sits there until Python 3.0 actually starts to come upon us.
What happened to "don't take this too seriously, I'm just trying to get the ball rolling"?
Nothing, it's called writing the email when I was tired and while I was trying to fall asleep realizing what I had done. =) It still needs to go out to c.l.py and will probably sit for a long while unpronounced. That's the reason I was saying that the transition plan needs to be fleshed out with 2.x, 2.x+1 version numbers instead of concrete ones like 2.5 . -Brett
[Brett]
The problem with existing code checking for this situation is that the situation itself is not the same as it will be if bare 'except's change::
try: ... except: ... except TerminatingException: ...
has never really been possible before, but will be if the PEP goes forward.
That's not an improvement. The above code fragment should trigger a gag reflex indicating that something is wrong with the proposed default for a bare except.
Having a catch-all for exceptions that a bare 'except' will skip that is more explicit than ``except BaseException`` seems reasonable to me.
The data gathered by Jack and Steven's research indicate that the number of cases where TerminatingException would be useful is ZERO. Try not to introduce a new builtin that no one will ever use. Try not to add a new word whose only function is to replace a two-word tuple (TOOWTDI). Try not to unnecessarily nest the tree (FITBN). Try not to propose solutions to problems that don't exist (PBP). Raymond
WindowsError ------------
This should be kept. Unlike module specific exceptions, this exception occurs in multiple places and diverse applications. It is appropriate to list as a builtin.
"Too O/S specific" is not a reason for eliminating this. Looking at the codebase there does not appear to be a good substitute. Eliminating this one would break code, decrease clarity, and cause modules to grow competing variants.
[Brett]
I unfortunately forgot to add that the exception would be moved under os, so it would be more of a renaming than a removal.
Isn't OSError already used for another purpose (non-platform dependent exceptions raised by the os module)? Raymond
On 8/10/05, Raymond Hettinger <raymond.hettinger@verizon.net> wrote:
WindowsError ------------
This should be kept. Unlike module specific exceptions, this exception occurs in multiple places and diverse applications. It is appropriate to list as a builtin.
"Too O/S specific" is not a reason for eliminating this. Looking at the codebase there does not appear to be a good substitute. Eliminating this one would break code, decrease clarity, and cause modules to grow competing variants.
[Brett]
I unfortunately forgot to add that the exception would be moved under os, so it would be more of a renaming than a removal.
Isn't OSError already used for another purpose (non-platform dependent exceptions raised by the os module)?
Don't quite follow what that has to do with making WindowsError become os.WindowsError. Yes, OSError is meant for platform-agnostic OS errors by the os module, but how does that affect the proposed move of WindowsError? -Brett
On Aug 9, 2005, at 7:15 PM, Raymond Hettinger wrote:
The data gathered by Jack and Steven's research indicate that the number of cases where TerminatingException would be useful is ZERO. Try not to introduce a new builtin that no one will ever use. Try not to add a new word whose only function is to replace a two-word tuple (TOOWTDI). Try not to unnecessarily nest the tree (FITBN). Try not to propose solutions to problems that don't exist (PBP).
I disagree. TerminatingException is useful. For the immediate future, I'd like to be able to write code like this (I'm assuming that "except:" means what it means now, because changing that for Py2.5 would be insane): try: TerminatingException except NameError: # compatibility with python < 2.5 TerminatingException = (KeyboardInterrupt, SystemExit) try: foo.... except TerminatingException: raise except: print "error message" What this gets me: 1) easy backwards compatibility with earlier pythons which still have KeyboardInterrupt and SystemExit under Exception and don't provide TerminatingException 2) I still catch string exceptions, in case anyone raises one 3) Forward compatibility with pythons that add more types of terminating exceptions. James
participants (5)
-
Brett Cannon
-
James Y Knight
-
Nick Coghlan
-
Raymond Hettinger
-
Raymond Hettinger