Update Rationale.

This commit is contained in:
Ka-Ping Yee 2005-05-15 23:53:56 +00:00
parent 43671683c9
commit 84ea75eb01
1 changed files with 47 additions and 32 deletions

View File

@ -102,22 +102,29 @@ Rationale
of tracebacks (from oldest to most recent frame) and because the of tracebacks (from oldest to most recent frame) and because the
actual thrown exception is easier to find on the last line. actual thrown exception is easier to find on the last line.
Java and Ruby both discard the current exception when an exception To keep things simpler, the C API calls for setting an exception
occurs in a 'catch'/'rescue' or 'finally'/'ensure' clause. Perl 5 will not automatically set the exception's '__context__'. Guido
lacks built-in structured exception handling. For Perl 6, RFC 88 van Rossum has has expressed concerns with making such changes [8].
proposes an exception mechanism that retains all the chained
exceptions in an array named @@. In that RFC, the most recently As for other languages, Java and Ruby both discard the original
raised exception is exposed for matching, as in this PEP; also, exception when another exception occurs in a 'catch'/'rescue' or
arbitrary expressions (possibly involving @@) can be evaluated for 'finally'/'ensure' clause. Perl 5 lacks built-in structured
exception matching. exception handling. For Perl 6, RFC 88 proposes an exception
mechanism that retains chained exceptions in an array named @@.
In that RFC, the most recently raised exception is exposed for
matching, as in this PEP; also, arbitrary expressions (possibly
involving @@) can be evaluated for exception matching.
Exceptions in C# contain a read-only 'InnerException' property that Exceptions in C# contain a read-only 'InnerException' property that
may point to another exception. This property is not set by the VM may point to another exception [9]. According to its documentation,
automatically. Instead, the constructors of exception objects all "When an exception X is thrown as a direct result of a previous
accept an optional 'innerException' argument to explicitly set this exception Y, the InnerException property of X should contain a
property. The C# documentation says "an exception that is thrown as reference to Y." This property is not set by the VM automatically;
a direct result of a previous exception should include a reference rather, all exception constructors take an optional 'innerException'
to the previous exception in the InnerException property." argument to set it explicitly. The '__cause__' attribute fulfills
the same purpose as InnerException, but this PEP proposes adding a
single method to the base Exception class rather than extending the
constructors of all exceptions.
The reason all three of these attributes are presented together in The reason all three of these attributes are presented together in
one proposal is that the '__traceback__' attribute provides one proposal is that the '__traceback__' attribute provides
@ -202,7 +209,11 @@ Explicit Exception Chaining
The '__cause__' attribute on exception objects is always initialized The '__cause__' attribute on exception objects is always initialized
to None. It is set by calling the 'setcause' method, a new method to None. It is set by calling the 'setcause' method, a new method
defined on the base Exception class. For convenience, this method defined on the base Exception class. For convenience, this method
returns the exception itself. returns the exception itself:
def setcause(self, cause):
self.__cause__ = cause
return self
In the following example, a database provides implementations for a In the following example, a database provides implementations for a
few different kinds of storage, with file storage as one kind. The few different kinds of storage, with file storage as one kind. The
@ -301,12 +312,10 @@ Enhanced Reporting
C API C API
To keep things simpler, the PyErr_Set* calls for setting exceptions The PyErr_Set* calls for setting exceptions will not set the
will not set the '__context__' attribute on exceptions. The BDFL has '__context__' attribute on exceptions. PyErr_NormalizeException
has expressed qualms with making such changes to PyErr_Set* [8]. will always set the 'traceback' attribute to its 'tb' argument and
the '__context__' and '__cause__' attributes to None.
PyErr_NormalizeException will always set the 'traceback' attribute
to its 'tb' argument and the '__context__' attribute to None.
A new API function, PyErr_SetContext(context), will help C A new API function, PyErr_SetContext(context), will help C
programmers provide chained exception information. This function programmers provide chained exception information. This function
@ -319,25 +328,28 @@ Compatibility
Chained exceptions expose the type of the most recent exception, so Chained exceptions expose the type of the most recent exception, so
they will still match the same 'except' clauses as they do now. they will still match the same 'except' clauses as they do now.
The proposed changes should not break any code except for code that The proposed changes should not break any code unless the code sets
currently sets or depends on the values of attributes named or uses attributes named '__context__', '__cause__', 'setcause', or
'__context__', '__cause__', or '__traceback__' on exception '__traceback__' on exception instances. As of 2005-05-12, the
instances. As of 2005-05-12, the Python standard library contains Python standard library contains no mention of such attributes.
no mention of such attributes.
Open Issues Open Issues
Walter Dörwald [9] expressed a desire to attach extra information Walter Dörwald [10] expressed a desire to attach extra information
to an exception during its upward propagation, without changing its to an exception during its upward propagation without changing its
type. This could be a useful feature, but it is not addressed by type. This could be a useful feature, but it is not addressed by
this PEP. It could conceivably be addressed by a separate PEP this PEP. It could conceivably be addressed by a separate PEP
establishing conventions for other informational attributes on establishing conventions for other informational attributes on
exceptions. exceptions.
It is not clear whether the '__context__' feature proposed here would It is not clear whether the '__context__' and '__cause__' features
be sufficient to cover all the use cases that Raymond Hettinger [1] proposed here would be sufficient to cover all the use cases that
originally had in mind. Raymond Hettinger [1] originally had in mind.
As written, this PEP makes it impossible to suppress '__context__',
since setting exc.__context__ to None will only result in it being
set again the moment that exc is raised.
The exception context is lost when a 'yield' statement is executed; The exception context is lost when a 'yield' statement is executed;
resuming the frame after the 'yield' does not restore the context. resuming the frame after the 'yield' does not restore the context.
@ -430,7 +442,10 @@ References
[8] Guido van Rossum discusses automatic chaining in PyErr_Set* [8] Guido van Rossum discusses automatic chaining in PyErr_Set*
http://mail.python.org/pipermail/python-dev/2003-June/036180.html http://mail.python.org/pipermail/python-dev/2003-June/036180.html
[9] Walter Dörwald suggests wrapping exceptions to add details [9] MSDN .NET Framework Library, "Exception.InnerException Property"
http://msdn.microsoft.com/library/en-us/cpref/html/frlrfsystemexceptionclassinnerexceptiontopic.asp
[10] Walter Dörwald suggests wrapping exceptions to add details
http://mail.python.org/pipermail/python-dev/2003-June/036148.html http://mail.python.org/pipermail/python-dev/2003-June/036148.html