2005-10-27 22:53:49 -04:00
|
|
|
|
PEP: 352
|
|
|
|
|
Title: Required Superclass for Exceptions
|
2005-10-31 18:31:40 -05:00
|
|
|
|
Version: $Revision$
|
|
|
|
|
Last-Modified: $Date$
|
2007-04-19 15:05:14 -04:00
|
|
|
|
Author: Brett Cannon, Guido van Rossum
|
2006-02-28 23:48:52 -05:00
|
|
|
|
Status: Final
|
2005-10-27 22:53:49 -04:00
|
|
|
|
Type: Standards Track
|
|
|
|
|
Content-Type: text/x-rst
|
|
|
|
|
Created: 27-Oct-2005
|
|
|
|
|
Post-History:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Abstract
|
|
|
|
|
========
|
|
|
|
|
|
|
|
|
|
In Python 2.4 and before, any (classic) class can be raised as an
|
2007-04-19 15:05:14 -04:00
|
|
|
|
exception. The plan for 2.5 was to allow new-style classes, but this
|
|
|
|
|
makes the problem worse -- it would mean *any* class (or
|
|
|
|
|
instance) can be raised! This is a problem as it prevents any
|
|
|
|
|
guarantees from being made about the interface of exceptions.
|
2006-02-28 23:48:52 -05:00
|
|
|
|
This PEP proposes introducing a new superclass that all raised objects
|
|
|
|
|
must inherit from. Imposing the restriction will allow a standard
|
2007-04-19 15:05:14 -04:00
|
|
|
|
interface for exceptions to exist that can be relied upon. It also
|
|
|
|
|
leads to a known hierarchy for all exceptions to adhere to.
|
2005-10-27 22:53:49 -04:00
|
|
|
|
|
2005-10-28 15:35:57 -04:00
|
|
|
|
One might counter that requiring a specific base class for a
|
|
|
|
|
particular interface is unPythonic. However, in the specific case of
|
|
|
|
|
exceptions there's a good reason (which has generally been agreed to
|
|
|
|
|
on python-dev): requiring hierarchy helps code that wants to *catch*
|
2005-10-27 22:53:49 -04:00
|
|
|
|
exceptions by making it possible to catch *all* exceptions explicitly
|
|
|
|
|
by writing ``except BaseException:`` instead of
|
|
|
|
|
``except *:``. [#hierarchy-good]_
|
|
|
|
|
|
|
|
|
|
Introducing a new superclass for exceptions also gives us the chance
|
|
|
|
|
to rearrange the exception hierarchy slightly for the better. As it
|
|
|
|
|
currently stands, all exceptions in the built-in namespace inherit
|
|
|
|
|
from Exception. This is a problem since this includes two exceptions
|
2006-02-10 14:48:38 -05:00
|
|
|
|
(KeyboardInterrupt and SystemExit) that often need to be excepted from
|
|
|
|
|
the application's exception handling: the default behavior of shutting
|
2007-04-19 15:05:14 -04:00
|
|
|
|
the interpreter down without a traceback is usually more desirable than
|
|
|
|
|
whatever the application might do (with the possible exception of
|
|
|
|
|
applications that emulate Python's interactive command loop with
|
|
|
|
|
``>>>`` prompt). Changing it so that these two exceptions inherit
|
|
|
|
|
from the common superclass instead of Exception will make it easy for
|
|
|
|
|
people to write ``except`` clauses that are not overreaching and not
|
|
|
|
|
catch exceptions that should propagate up.
|
2005-10-27 22:53:49 -04:00
|
|
|
|
|
|
|
|
|
This PEP is based on previous work done for PEP 348 [#pep348]_.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Requiring a Common Superclass
|
|
|
|
|
=============================
|
|
|
|
|
|
|
|
|
|
This PEP proposes introducing a new exception named BaseException that
|
2007-04-19 15:05:14 -04:00
|
|
|
|
is a new-style class and has a single attribute, ``args``. Below
|
2006-03-01 19:36:20 -05:00
|
|
|
|
is the code as the exception will work in Python 3.0 (how it will
|
|
|
|
|
work in Python 2.x is covered in the `Transition Plan`_ section)::
|
2005-10-27 22:53:49 -04:00
|
|
|
|
|
|
|
|
|
class BaseException(object):
|
|
|
|
|
|
|
|
|
|
"""Superclass representing the base of the exception hierarchy.
|
|
|
|
|
|
2007-04-19 15:05:14 -04:00
|
|
|
|
Provides an 'args' attribute that contains all arguments passed
|
|
|
|
|
to the constructor. Suggested practice, though, is that only a
|
|
|
|
|
single string argument be passed to the constructor.
|
|
|
|
|
|
2005-10-27 22:53:49 -04:00
|
|
|
|
"""
|
|
|
|
|
|
2007-04-19 15:05:14 -04:00
|
|
|
|
def __init__(self, *args):
|
|
|
|
|
"""Set the 'args' attribute'"""
|
|
|
|
|
self.args = args
|
2005-10-27 22:53:49 -04:00
|
|
|
|
|
|
|
|
|
def __str__(self):
|
2007-04-19 15:05:14 -04:00
|
|
|
|
"""Return the str of
|
|
|
|
|
``args[0] if len(args) == 1 else args``."""
|
|
|
|
|
if len(self.args) == 1:
|
|
|
|
|
return str(self.args[0])
|
|
|
|
|
else:
|
|
|
|
|
return str(self.args)
|
2005-10-27 22:53:49 -04:00
|
|
|
|
|
|
|
|
|
def __repr__(self):
|
2007-04-19 15:05:14 -04:00
|
|
|
|
return "%s(*%s)" % (self.__class__.__name__, repr(self.args))
|
2005-10-27 22:53:49 -04:00
|
|
|
|
|
2007-01-18 14:22:33 -05:00
|
|
|
|
|
2007-04-19 15:05:14 -04:00
|
|
|
|
No restriction is placed upon what may be passed in for ``args``
|
2007-01-18 14:22:33 -05:00
|
|
|
|
for backwards-compatibility reasons. In practice, though, only
|
2007-04-19 15:05:14 -04:00
|
|
|
|
a single string argument should be used. This keeps the string
|
|
|
|
|
representation of the exception to be a useful message about the
|
|
|
|
|
exception that is human-readable; this is why the ``__str__`` method
|
|
|
|
|
special-cases on length-1 ``args`` value. Including programmatic
|
|
|
|
|
information (e.g., an error code number) should be stored as a
|
|
|
|
|
separate attribute in a subclass.
|
2005-10-27 22:53:49 -04:00
|
|
|
|
|
|
|
|
|
The ``raise`` statement will be changed to require that any object
|
|
|
|
|
passed to it must inherit from BaseException. This will make sure
|
|
|
|
|
that all exceptions fall within a single hierarchy that is anchored at
|
|
|
|
|
BaseException [#hierarchy-good]_. This also guarantees a basic
|
|
|
|
|
interface that is inherited from BaseException. The change to
|
|
|
|
|
``raise`` will be enforced starting in Python 3.0 (see the `Transition
|
|
|
|
|
Plan`_ below).
|
|
|
|
|
|
|
|
|
|
With BaseException being the root of the exception hierarchy,
|
|
|
|
|
Exception will now inherit from it.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Exception Hierarchy Changes
|
|
|
|
|
===========================
|
|
|
|
|
|
|
|
|
|
With the exception hierarchy now even more important since it has a
|
|
|
|
|
basic root, a change to the existing hierarchy is called for. As it
|
|
|
|
|
stands now, if one wants to catch all exceptions that signal an error
|
|
|
|
|
*and* do not mean the interpreter should be allowed to exit, you must
|
2005-10-28 15:35:57 -04:00
|
|
|
|
specify all but two exceptions specifically in an ``except`` clause
|
|
|
|
|
or catch the two exceptions separately and then re-raise them and
|
|
|
|
|
have all other exceptions fall through to a bare ``except`` clause::
|
|
|
|
|
|
|
|
|
|
except (KeyboardInterrupt, SystemExit):
|
|
|
|
|
raise
|
|
|
|
|
except:
|
|
|
|
|
...
|
|
|
|
|
|
2005-10-27 22:53:49 -04:00
|
|
|
|
That is needlessly explicit. This PEP proposes moving
|
|
|
|
|
KeyboardInterrupt and SystemExit to inherit directly from
|
|
|
|
|
BaseException.
|
|
|
|
|
|
2005-10-28 15:35:57 -04:00
|
|
|
|
::
|
|
|
|
|
|
|
|
|
|
- BaseException
|
|
|
|
|
|- KeyboardInterrupt
|
|
|
|
|
|- SystemExit
|
|
|
|
|
|- Exception
|
|
|
|
|
|- (all other current built-in exceptions)
|
|
|
|
|
|
2005-10-27 22:53:49 -04:00
|
|
|
|
Doing this makes catching Exception more reasonable. It would catch
|
|
|
|
|
only exceptions that signify errors. Exceptions that signal that the
|
2006-05-08 12:11:39 -04:00
|
|
|
|
interpreter should exit will not be caught and thus be allowed to
|
2005-10-27 22:53:49 -04:00
|
|
|
|
propagate up and allow the interpreter to terminate.
|
|
|
|
|
|
|
|
|
|
KeyboardInterrupt has been moved since users typically expect an
|
|
|
|
|
application to exit when the press the interrupt key (usually Ctrl-C).
|
|
|
|
|
If people have overly broad ``except`` clauses the expected behaviour
|
|
|
|
|
does not occur.
|
|
|
|
|
|
|
|
|
|
SystemExit has been moved for similar reasons. Since the exception is
|
|
|
|
|
raised when ``sys.exit()`` is called the interpreter should normally
|
|
|
|
|
be allowed to terminate. Unfortunately overly broad ``except``
|
2006-03-09 13:22:01 -05:00
|
|
|
|
clauses can prevent the explicitly requested exit from occurring.
|
2005-10-27 22:53:49 -04:00
|
|
|
|
|
|
|
|
|
To make sure that people catch Exception most of the time, various
|
|
|
|
|
parts of the documentation and tutorials will need to be updated to
|
|
|
|
|
strongly suggest that Exception be what programmers want to use. Bare
|
|
|
|
|
``except`` clauses or catching BaseException directly should be
|
|
|
|
|
discouraged based on the fact that KeyboardInterrupt and SystemExit
|
|
|
|
|
almost always should be allowed to propagate up.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Transition Plan
|
|
|
|
|
===============
|
|
|
|
|
|
|
|
|
|
Since semantic changes to Python are being proposed, a transition plan
|
|
|
|
|
is needed. The goal is to end up with the new semantics being used in
|
|
|
|
|
Python 3.0 while providing a smooth transition for 2.x code. All
|
|
|
|
|
deprecations mentioned in the plan will lead to the removal of the
|
2006-09-30 16:33:33 -04:00
|
|
|
|
semantics starting in the version following the initial deprecation.
|
2005-10-27 22:53:49 -04:00
|
|
|
|
|
2006-03-01 19:36:20 -05:00
|
|
|
|
Here is BaseException as implemented in the 2.x series::
|
|
|
|
|
|
|
|
|
|
class BaseException(object):
|
|
|
|
|
|
|
|
|
|
"""Superclass representing the base of the exception hierarchy.
|
|
|
|
|
|
2007-04-19 15:05:14 -04:00
|
|
|
|
The __getitem__ method is provided for backwards-compatibility
|
|
|
|
|
and will be deprecated at some point. The 'message' attribute
|
|
|
|
|
is also deprecated.
|
2006-03-01 19:36:20 -05:00
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def __init__(self, *args):
|
2007-04-19 15:05:14 -04:00
|
|
|
|
"""Set the 'args' attribute."""
|
2006-03-01 19:36:20 -05:00
|
|
|
|
self.args = args
|
|
|
|
|
|
|
|
|
|
def __str__(self):
|
2007-04-19 15:05:14 -04:00
|
|
|
|
"""Return the str of args[0] or args, depending on length."""
|
2006-03-01 19:36:20 -05:00
|
|
|
|
return str(self.args[0]
|
|
|
|
|
if len(self.args) <= 1
|
|
|
|
|
else self.args)
|
|
|
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
|
func_args = repr(self.args) if self.args else "()"
|
|
|
|
|
return self.__class__.__name__ + func_args
|
|
|
|
|
|
|
|
|
|
def __getitem__(self, index):
|
|
|
|
|
"""Index into arguments passed in during instantiation.
|
|
|
|
|
|
|
|
|
|
Provided for backwards-compatibility and will be
|
|
|
|
|
deprecated.
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
return self.args[index]
|
|
|
|
|
|
2007-04-19 15:05:14 -04:00
|
|
|
|
def _get_message(self):
|
|
|
|
|
"""Method for 'message' property."""
|
|
|
|
|
warnings.warn("the 'message' attribute has been deprecated "
|
|
|
|
|
"since Python 2.6")
|
|
|
|
|
return self.args[0] if len(args) == 1 else ''
|
|
|
|
|
|
|
|
|
|
message = property(_get_message)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2006-03-01 19:36:20 -05:00
|
|
|
|
|
2005-11-22 14:41:50 -05:00
|
|
|
|
Deprecation of features in Python 2.9 is optional. This is because it
|
2006-02-01 17:35:30 -05:00
|
|
|
|
is not known at this time if Python 2.9 (which is slated to be the
|
|
|
|
|
last version in the 2.x series) will actively deprecate features that
|
|
|
|
|
will not be in 3.0 . It is conceivable that no deprecation warnings
|
|
|
|
|
will be used in 2.9 since there could be such a difference between 2.9
|
|
|
|
|
and 3.0 that it would make 2.9 too "noisy" in terms of warnings. Thus
|
|
|
|
|
the proposed deprecation warnings for Python 2.9 will be revisited
|
|
|
|
|
when development of that version begins to determine if they are still
|
|
|
|
|
desired.
|
2005-11-22 14:41:50 -05:00
|
|
|
|
|
2007-04-19 15:05:14 -04:00
|
|
|
|
* Python 2.5 [done]
|
2005-10-27 22:53:49 -04:00
|
|
|
|
|
2007-09-05 18:54:10 -04:00
|
|
|
|
- all standard exceptions become new-style classes [done]
|
2005-10-27 22:53:49 -04:00
|
|
|
|
|
2007-09-05 18:54:10 -04:00
|
|
|
|
- introduce BaseException [done]
|
2005-10-27 22:53:49 -04:00
|
|
|
|
|
2007-09-05 18:54:10 -04:00
|
|
|
|
- Exception, KeyboardInterrupt, and SystemExit inherit from
|
|
|
|
|
BaseException [done]
|
2005-10-27 22:53:49 -04:00
|
|
|
|
|
2007-09-05 18:54:10 -04:00
|
|
|
|
- deprecate raising string exceptions [done]
|
2005-10-27 22:53:49 -04:00
|
|
|
|
|
2007-09-05 18:54:10 -04:00
|
|
|
|
* Python 2.6 [done]
|
2005-10-27 22:53:49 -04:00
|
|
|
|
|
2007-04-19 15:05:14 -04:00
|
|
|
|
- deprecate catching string exceptions [done]
|
|
|
|
|
|
2007-09-05 18:54:10 -04:00
|
|
|
|
- deprecate ``message`` attribute (see `Retracted Ideas`_) [done]
|
2005-10-27 22:53:49 -04:00
|
|
|
|
|
|
|
|
|
* Python 2.7
|
|
|
|
|
|
|
|
|
|
- deprecate raising exceptions that do not inherit from BaseException
|
|
|
|
|
|
2007-04-19 15:05:14 -04:00
|
|
|
|
- remove ``message`` attribute
|
|
|
|
|
|
2005-10-27 22:53:49 -04:00
|
|
|
|
* Python 2.8
|
|
|
|
|
|
|
|
|
|
- deprecate catching exceptions that do not inherit from BaseException
|
|
|
|
|
|
2005-10-28 23:22:31 -04:00
|
|
|
|
* Python 2.9
|
|
|
|
|
|
2007-04-19 15:05:14 -04:00
|
|
|
|
- deprecate ``__getitem__`` (optional)
|
2005-10-27 22:53:49 -04:00
|
|
|
|
|
2007-09-05 18:54:10 -04:00
|
|
|
|
* Python 3.0 [done]
|
2005-10-31 14:22:43 -05:00
|
|
|
|
|
2006-02-10 14:48:38 -05:00
|
|
|
|
- drop everything that was deprecated above:
|
|
|
|
|
|
2007-04-19 15:05:14 -04:00
|
|
|
|
+ string exceptions (both raising and catching) [done]
|
|
|
|
|
|
|
|
|
|
+ all exceptions must inherit from BaseException [done]
|
2006-02-10 14:48:38 -05:00
|
|
|
|
|
2007-09-05 18:54:10 -04:00
|
|
|
|
+ drop ``__getitem__``, ``message`` [done]
|
2006-02-10 14:48:38 -05:00
|
|
|
|
|
2005-10-31 14:22:43 -05:00
|
|
|
|
|
2007-04-19 15:05:14 -04:00
|
|
|
|
Retracted Ideas
|
|
|
|
|
===============
|
2005-10-27 22:53:49 -04:00
|
|
|
|
|
2007-04-19 15:05:14 -04:00
|
|
|
|
A previous version of this PEP that was implemented in Python 2.5
|
|
|
|
|
included a 'message' attribute on BaseException. Its purpose was to
|
|
|
|
|
begin a transition to BaseException accepting only a single argument.
|
|
|
|
|
This was to tighten the interface and to force people to use
|
|
|
|
|
attributes in subclasses to carry arbitrary information with an
|
|
|
|
|
exception instead of cramming it all into ``args``.
|
|
|
|
|
|
|
|
|
|
Unfortunately, while implementing the removal of the ``args``
|
|
|
|
|
attribute in Python 3.0 at the PyCon 2007 sprint
|
|
|
|
|
[#pycon2007-sprint-email]_, it was discovered that the transition was
|
|
|
|
|
very painful, especially for C extension modules. It was decided that
|
|
|
|
|
it would be better to deprecate the ``message`` attribute in
|
2007-09-13 18:49:14 -04:00
|
|
|
|
Python 2.6 (and remove it in Python 2.7 and Python 3.0) and consider a
|
2007-04-19 15:05:14 -04:00
|
|
|
|
more long-term transition strategy in Python 3.0 to remove
|
|
|
|
|
multiple-argument support in BaseException in preference of accepting
|
|
|
|
|
only a single argument. Thus the introduction of ``message`` and the
|
|
|
|
|
original deprecation of ``args`` has been retracted.
|
2006-02-01 17:35:30 -05:00
|
|
|
|
|
|
|
|
|
|
2005-10-27 22:53:49 -04:00
|
|
|
|
References
|
|
|
|
|
==========
|
|
|
|
|
|
|
|
|
|
.. [#pep348] PEP 348 (Exception Reorganization for Python 3.0)
|
|
|
|
|
http://www.python.org/peps/pep-0348.html
|
|
|
|
|
|
|
|
|
|
.. [#hierarchy-good] python-dev Summary for 2004-08-01 through 2004-08-15
|
|
|
|
|
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
|
|
|
|
|
|
2006-02-01 17:35:30 -05:00
|
|
|
|
.. [#SF_1104669] SF patch #1104669 (new-style exceptions)
|
|
|
|
|
http://www.python.org/sf/1104669
|
|
|
|
|
|
2007-04-19 15:05:14 -04:00
|
|
|
|
.. [#pycon2007-sprint-email] python-3000 email ("How far to go with cleaning up exceptions")
|
|
|
|
|
http://mail.python.org/pipermail/python-3000/2007-March/005911.html
|
|
|
|
|
|
2005-10-27 22:53:49 -04:00
|
|
|
|
|
|
|
|
|
Copyright
|
|
|
|
|
=========
|
|
|
|
|
|
|
|
|
|
This document has been placed in the public domain.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
..
|
|
|
|
|
Local Variables:
|
|
|
|
|
mode: indented-text
|
|
|
|
|
indent-tabs-mode: nil
|
|
|
|
|
sentence-end-double-space: t
|
|
|
|
|
fill-column: 70
|
|
|
|
|
End:
|