Movatterモバイル変換


[0]ホーム

URL:


Following system colour schemeSelected dark colour schemeSelected light colour scheme

Python Enhancement Proposals

PEP 348 – Exception Reorganization for Python 3.0

Author:
Brett Cannon <brett at python.org>
Status:
Rejected
Type:
Standards Track
Created:
28-Jul-2005
Post-History:


Table of Contents

Note

This PEP has been rejected[16].

Abstract

Python, as of version 2.4, has 38 exceptions (including warnings) inthe built-in namespace in a rather shallow hierarchy. Theseclasses have come about over the years without a chance to learn fromexperience. This PEP proposes doing a reorganization of the hierarchyfor Python 3.0 when backwards-compatibility is not as much of anissue.

Along with this reorganization, adding a requirement that allobjects passed to araise statement must inherit from a specificsuperclass is proposed. This is to have guarantees about the basicinterface of exceptions and to further enhance the natural hierarchyof exceptions.

Lastly, bareexcept clauses will be changed to be semanticallyequivalent toexceptException. Most people currently use bareexcept clause for this purpose and with the exception hierarchyreorganization becomes a viable default.

Rationale For Wanting Change

Exceptions are a critical part of Python. While exceptions aretraditionally used to signal errors in a program, they have also grownto be used for flow control for things such as iterators.

While their importance is great, there is a lack of structure to them.This stems from the fact that any object can be raised as anexception. Because of this you have no guarantee in terms of whatkind of object will be raised, destroying any possible hierarchyraised objects might adhere to.

But exceptions do have a hierarchy, showing the severity of theexception. The hierarchy also groups related exceptions together tosimplify catching them inexcept clauses. To allow people tobe able to rely on this hierarchy, a common superclass that allraise objects must inherit from is being proposed. It also allowsguarantees about the interface to raised objects to be made (seePEP 344). A discussion about all of this has occurredbefore on python-dev[1].

As bareexcept clauses stand now, they catchall exceptions.While this can be handy, it is rather overreaching for the commoncase. Thanks to having a required superclass, catching allexceptions is as easy as catching just one specific exception.This allows bareexcept clauses to be used for a more usefulpurpose.Once again, this has been discussed on python-dev[2].

Finally, slight changes to the exception hierarchy will make it muchmore reasonable in terms of structure. By minor rearrangingexceptionsthat should not typically be caught can be allowed to propagate to thetop of the execution stack, terminating the interpreter as intended.

Philosophy of Reorganization

For the reorganization of the hierarchy, there was a generalphilosophy followed that developed from discussion of earlier draftsof this PEP[4],[5],[6],[7],[8],[9].First and foremost was to not break anythingthat works. This meant that renaming exceptions was out of thequestion unless the name was deemed severely bad. Thisalso meant no removal of exceptions unless they were viewed astruly misplaced. The introduction of new exceptions were only done insituations where there might be a use for catching a superclass of acategory of exceptions. Lastly, existing exceptions would have theirinheritance tree changed only if it was felt they were trulymisplaced to begin with.

For all new exceptions, the proper suffix had to be chosen. Forthose that signal an error, “Error” is to be used. If the exceptionis a warning, then “Warning”. “Exception” is to be used when noneof the other suffixes are proper to use and no specific suffix isa better fit.

After that it came down to choosing which exceptions should andshould not inherit from Exception. This was for the purpose ofmaking bareexcept clauses more useful.

Lastly, the entire existing hierarchy had to inherit from the newexception meant to act as the required superclass for all exceptionsto inherit from.

New Hierarchy

Note

Exceptions flagged with “stricter inheritance” will nolonger inherit from a certain class. A “broader inheritance” flagmeans a class has been added to the exception’s inheritance tree.All comparisons are against the Python 2.4 exception hierarchy.

+-- BaseException (new; broader inheritance for subclasses)    +-- Exception        +-- GeneratorExit (defined inPEP 342)        +-- StandardError            +-- ArithmeticError                +-- DivideByZeroError                +-- FloatingPointError                +-- OverflowError            +-- AssertionError            +-- AttributeError            +-- EnvironmentError                +-- IOError                +-- EOFError                +-- OSError            +-- ImportError            +-- LookupError                +-- IndexError                +-- KeyError            +-- MemoryError            +-- NameError                +-- UnboundLocalError            +-- NotImplementedError (stricter inheritance)            +-- SyntaxError                +-- IndentationError                    +-- TabError            +-- TypeError            +-- RuntimeError            +-- UnicodeError                +-- UnicodeDecodeError                +-- UnicodeEncodeError                +-- UnicodeTranslateError            +-- ValueError            +-- ReferenceError        +-- StopIteration        +-- SystemError        +-- Warning            +-- DeprecationWarning            +-- FutureWarning            +-- PendingDeprecationWarning            +-- RuntimeWarning            +-- SyntaxWarning            +-- UserWarning        + -- WindowsError    +-- KeyboardInterrupt (stricter inheritance)    +-- SystemExit (stricter inheritance)

Differences Compared to Python 2.4

A more thorough explanation of terms is needed when discussinginheritance changes. Inheritance changes result in either broader ormore restrictive inheritance. “Broader” is when a class has aninheritance tree likecls,A and then becomescls,B,A.“Stricter” is the reverse.

BaseException

The superclass that all exceptions must inherit from. It’s name waschosen to reflect that it is at the base of the exception hierarchywhile being an exception itself. “Raisable” was considered as a name,it was passed on because its name did not properly reflect the factthat it is an exception itself.

Direct inheritance of BaseException is not expected, and willbe discouraged for the general case. Most user-definedexceptions should inherit from Exception instead. This allowscatching Exception to continue to work in the common case of catchingall exceptions that should be caught. Direct inheritance ofBaseException should only be done in cases where an entirely newcategory of exception is desired.

But, for cases where allexceptions should be caught blindly,exceptBaseException willwork.

KeyboardInterrupt and SystemExit

Both exceptions are no longer under Exception. This is to allow bareexcept clauses to act as a more viable default case by catchingexceptions that inherit from Exception. With both KeyboardInterruptand SystemExit acting as signals that the interpreter is expected toexit, catching them in the common case is the wrong semantics.

NotImplementedError

Inherits from Exception instead of from RuntimeError.

Originally inheriting from RuntimeError, NotImplementedError does nothave any direct relation to the exception meant for use in user codeas a quick-and-dirty exception. Thus it now directly inherits fromException.

Required Superclass forraise

By requiring all objects passed to araise statement to inheritfrom a specific superclass, all exceptions are guaranteed to havecertain attributes. IfPEP 344 is accepted, the attributesoutlined there will be guaranteed to be on all exceptions raised.This should help facilitate debugging by making the querying ofinformation from exceptions much easier.

The proposed hierarchy has BaseException as the required base class.

Implementation

Enforcement is straightforward. ModifyingRAISE_VARARGS to do aninheritance check first before raising an exception should be enough.For the C API, all functions that set an exception will have the sameinheritance check applied.

Bareexcept Clauses Catch Exception

In most existing Python 2.4 code, bareexcept clauses are toobroad in the exceptions they catch. Typically only exceptions thatsignal an error are desired to be caught. This means that exceptionsthat are used to signify that the interpreter should exit should notbe caught in the common case.

With KeyboardInterrupt and SystemExit moved to inherit fromBaseException instead of Exception, changing bareexcept clausesto act asexceptException becomes a much more reasonabledefault. This change also will break very little code since thesesemantics are what most people want for bareexcept clauses.

The complete removal of bareexcept clauses has been argued for.The case has been made that they violate both Only One Way To Do It(OOWTDI) and Explicit Is Better Than Implicit (EIBTI) as listed in theZen of Python. But Practicality Beats Purity (PBP), also inthe Zen of Python, trumps both of these in this case. The BDFL hasstated that bareexcept clauses will work this way[14].

Implementation

The compiler will emit the bytecode forexceptException whenevera bareexcept clause is reached.

Transition Plan

Because of the complexity and clutter that would be required to addall features planned in this PEP, the transition plan is very simple.In Python 2.5 BaseException is added. In Python 3.0, all remainingfeatures (required superclass, change in inheritance, bareexceptclauses becoming the same asexceptException) will go intoaffect. In order to make all of this work in a backwards-compatibleway in Python 2.5 would require very deep hacks in the exceptionmachinery which could be error-prone and lead to a slowdown inperformance for little benefit.

To help with the transition, the documentation will be changed toreflect several programming guidelines:

  • When one wants to catchall exceptions, catch BaseException
  • To catch all exceptions that do not represent the termination ofthe interpreter, catch Exception explicitly
  • Explicitly catch KeyboardInterrupt and SystemExit; don’t rely oninheritance from Exception to lead to the capture
  • Always catch NotImplementedError explicitly instead of relying onthe inheritance from RuntimeError

The documentation for the ‘exceptions’ module[3],tutorial[15], andPEP 290 will all requireupdating.

Rejected Ideas

DeprecationWarning Inheriting From PendingDeprecationWarning

This was originally proposed because a DeprecationWarning can beviewed as a PendingDeprecationWarning that is being removed in thenext version. But since enough people thought the inheritance couldlogically work the other way around, the idea was dropped.

AttributeError Inheriting From TypeError or NameError

Viewing attributes as part of the interface of a type caused the ideaof inheriting from TypeError. But that partially defeats the thinkingof duck typing and thus the idea was dropped.

Inheriting from NameError was suggested because objects can be viewedas having their own namespace where the attributes live and when anattribute is not found it is a namespace failure. This was alsodropped as a possibility since not everyone shared this view.

Removal of EnvironmentError

Originally proposed based on the idea that EnvironmentError was anunneeded distinction, the BDFL overruled this idea[10].

Introduction of MacError and UnixError

Proposed to add symmetry to WindowsError, the BDFL said they won’t beused enough[10]. The idea of then removing WindowsErrorwas proposed and accepted as reasonable, thus completely negating theidea of adding these exceptions.

SystemError Subclassing SystemExit

Proposed because a SystemError is meant to lead to a system exit, theidea was removed since CriticalError indicates this better.

ControlFlowException Under Exception

It has been suggested that ControlFlowException should inherit fromException. This idea has been rejected based on the thinking thatcontrol flow exceptions typically do not all need to be caught by asingleexcept clause.

Rename NameError to NamespaceError

NameError is considered more succinct and leaves open no possiblemistyping ofthe capitalization of “Namespace”[11].

Renaming RuntimeError or Introducing SimpleError

The thinking was that RuntimeError was in no way an obvious name foran exception meant to be used when a situation did not call for thecreation of a new exception. The renaming was rejected on the basisthat the exception is already used throughout the interpreter[12].Rejection of SimpleError was founded on the thought that peopleshould be free to use whatever exception they choose and not have oneso blatantly suggested[13].

Renaming Existing Exceptions

Various renamings were suggested but non garnered more than a +0 vote(renaming ReferenceError to WeakReferenceError). The thinking wasthat the existing names were fine and no one had actively complainedabout them ever. To minimize backwards-compatibility issues andcausing existing Python programmers extra pain, the renamings wereremoved.

Have EOFError Subclass IOError

The original thought was that since EOFError deals directly with I/O,it shouldsubclass IOError. But since EOFError is used more as a signal that aneventhas occurred (the exhaustion of an I/O port), it should not subclasssuch a specific error exception.

Have MemoryError and SystemError Have a Common Superclass

Both classes deal with the interpreter, so why not have them have acommonsuperclass? Because one of them means that the interpreter is in astate that it should not recover from while the other does not.

Common Superclass for PendingDeprecationWarning and DeprecationWarning

Grouping the deprecation warning exceptions together makes intuitivesense.But this sensical idea does not extend well when one considers howrarely either warning is used, let along at the same time.

Removing WindowsError

Originally proposed based on the idea that having such aplatform-specific exception should not be in the built-in namespace.It turns out, though, enough code exists that uses the exception towarrant it staying.

Superclass for KeyboardInterrupt and SystemExit

Proposed to make catching non-Exception inheriting exceptions easieralong with easing the transition to the new hierarchy, the idea wasrejected by the BDFL[14]. The argument that existingcode did not show enough instances of the pair of exceptions beingcaught and thus did not justify cluttering the built-in namespacewas used.

Acknowledgements

Thanks to Robert Brewer, Josiah Carlson, Alyssa Coghlan, TimothyDelaney, Jack Diedrich, Fred L. Drake, Jr., Philip J. Eby, Greg Ewing,James Y. Knight, MA Lemburg, Guido van Rossum, Stephen J. Turnbull,Raymond Hettinger, and everyone else I missed for participating in thediscussion.

References

[1]
python-dev Summary (An exception is anexception, unless it doesn’t inherit from Exception)http://www.python.org/dev/summary/2004-08-01_2004-08-15.html#an-exception-is-an-exception-unless-it-doesn-t-inherit-from-exception
[2]
python-dev email (PEP, take 2: ExceptionReorganization for Python 3.0)https://mail.python.org/pipermail/python-dev/2005-August/055116.html
[3]
exceptions modulehttp://docs.python.org/library/exceptions.html
[4]
python-dev thread (Pre-PEP: ExceptionReorganization for Python 3.0)https://mail.python.org/pipermail/python-dev/2005-July/055020.html,https://mail.python.org/pipermail/python-dev/2005-August/055065.html
[5]
python-dev thread (PEP, take 2: ExceptionReorganization for Python 3.0)https://mail.python.org/pipermail/python-dev/2005-August/055103.html
[6]
python-dev thread (Reorg PEP checked in)https://mail.python.org/pipermail/python-dev/2005-August/055138.html
[7]
python-dev thread (Major revision of PEP 348 committed)https://mail.python.org/pipermail/python-dev/2005-August/055199.html
[8]
python-dev thread (Exception Reorg PEP revised yet again)https://mail.python.org/pipermail/python-dev/2005-August/055292.html
[9]
python-dev thread (PEP 348 (exception reorg) revised again)https://mail.python.org/pipermail/python-dev/2005-August/055412.html
[10] (1,2)
python-dev email (Pre-PEP: Exception Reorganizationfor Python 3.0)https://mail.python.org/pipermail/python-dev/2005-July/055019.html
[11]
python-dev email (PEP, take 2: Exception Reorganization forPython 3.0)https://mail.python.org/pipermail/python-dev/2005-August/055159.html
[12]
python-dev email (Exception Reorg PEP checked in)https://mail.python.org/pipermail/python-dev/2005-August/055149.html
[13]
python-dev email (Exception Reorg PEP checked in)https://mail.python.org/pipermail/python-dev/2005-August/055175.html
[14] (1,2)
python-dev email (PEP 348 (exception reorg) revised again)https://mail.python.org/pipermail/python-dev/2005-August/055423.html
[15]
Python Tutorialhttp://docs.python.org/tutorial/
[16]
python-dev email (Bare except clauses in PEP 348)https://mail.python.org/pipermail/python-dev/2005-August/055676.html

Copyright

This document has been placed in the public domain.


Source:https://github.com/python/peps/blob/main/peps/pep-0348.rst

Last modified:2025-02-01 08:59:27 GMT


[8]ページ先頭

©2009-2025 Movatter.jp