M.-A. Lemburg wrote:
The reason for my -1 on the renaming and reordering is that it would completely break compatibility of Python 2.x applications with Python 3. Furthermore, there would be next to no chance of writing new applications that run in Python 3 and 2, so you have breakage in both directions.
Whether this is desired or not is a different discussion, I just want to point out some important things to consider:
When moving from Python 2.x to 3.0, renaming could be solved with the help of some scripts, grep et al. However, there would have to be a good reason for each of these renamings, otherwise this only introduces additional porting overhead. Aliases might be a way to provide soft introduction.
Something that scripts will not be able to help with are changes in the inheritance tree, e.g. if an application catches a ValueError, the programmer might also expect UnicodeErrors to get caught, if the application catches a TypeError, this may not be aware that the TypeError could actually be an AttributeError.
I think the problems with this can be minimised by avoiding making changes we don't need to. I think only a few changes are needed to get a significantly cleaner structure.
Here's a fairly minimal proposal, which is closer to the existing 2.4 structure:
New Hierarchy =============
Raisable (formerly Exception) +-- CriticalException (new) +-- KeyboardInterrupt +-- MemoryError +-- SystemError +-- ControlFlowException (new) +-- GeneratorExit +-- StopIteration +-- SystemExit +-- Exception (formerly StandardError) +-- AssertionError +-- AttributeError +-- ImportError +-- TypeError +-- WeakReferenceError (formerly ReferenceError) +-- ArithmeticError +-- FloatingPointError +-- DivideByZeroError +-- OverflowError +-- EnvironmentError +-- OSError +-- WindowsError (possibly remove this from builtins) +-- IOError +-- EOFError +-- LookupError +-- IndexError +-- KeyError +-- NameError +-- UnboundLocalError +-- RuntimeError +-- NotImplementedError +-- SyntaxError +-- IndentationError +-- TabError +-- ValueError +-- UnicodeError +-- UnicodeDecodeError +-- UnicodeEncodeError +-- UnicodeTranslateError +-- Warning +-- DeprecationWarning +-- FutureWarning +-- PendingDeprecationWarning +-- SemanticsWarning (formerly RuntimeWarning) +-- SyntaxWarning +-- UserWarning
Changes from Py 2.4: ====================
The big changes:
Exception renamed to Raisable StandardError renamed to Exception Rationale for this renaming is that too many people do "except Exception:" when they really mean "except StandardError:". Most applications should cope with this semantics change without much hassle, as the only exceptions that "slip through the net" are KeyboardInterrupt, MemoryError and SystemError.
New exception ControlFlowException Make SystemExit a subclass of this Make StopIteration a subclass of this Make GeneratorExit a subclass of this In Python 2.4, the only two exceptions not under StandardError are SystemExit and StopIteration. These are both control flow exceptions - one indicates termination of the application, the other indicates completion of an iterator. Python 2.5 will most likely add GeneratorExit for termination of a generator. Grouping these under a common superclass has a few benefits. - documentation benefit (its obvious why these exceptions are special) - OOWTDI for breaking out of nested loops: raise and catch CFE - module developers can use it to clearly mark their own CFE classes
New exception CriticalException Make KeyboardInterrupt a subclass of this Make MemoryError a subclass of this Make SystemError a subclass of this All of these exceptions inherit from StandardError in Python 2.4, but each of them indicates something is seriously wrong. KI indicates Ctrl-C has been pressed, ME indicates the VM has run out of memory, and SE indicates the VM's internals are out of whack. There isn't much a program can or should be doing about these. Certainly, none of them should be getting caught by "except Exception:".
The following changes are comparatively minor cleanups:
Make EOFError a subclass of IOError Trying to read past the end of a file _is_ an IOError!
ReferenceError renamed to WeakReferenceError This recaptures the context that was lost when making this a builtin.
RuntimeWarning renamed to SemanticsWarning This better captures the meaning of the warning, and avoids confusion with RuntimeError, which has a very different purpose.
A few key differences from Brett's original proposal:
I severely culled the Critical Exceptions list. The CE list was dropped back to those where either the user has indicated they want the program to stop, or the VM has reported that there is a severe problem. Everything else went back under Exception.
ControlFlowException was made a peer category to Exception and CriticalException. This preserves the location of StopIteration. I also added SystemExit to this group, because it relates to control flow of the entire application (i.e., it is the graceful way to say "get out now").
AttributeError is left as a standalone exception.
NameError is not renamed as it actually indicates: - this name is not in locals - this name is not in any containing lexical scope - this name is not in the module globals - this name is not in builtins UnboundLocalError indicates "this name is in locals, but was referenced before it was set". So, I'm not sure what UnboundGlobalError would actually _mean_.
Various other exceptions (RuntimeError, EnvironmentError, etc) either weren't deleted or weren't moved. The changes I kept had decent justifications for how they improved the clarity of the exception structure - those I dropped were those I haven't found convincing.