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
actual thrown exception is easier to find on the last line.
Java and Ruby both discard the current exception when an exception
occurs in a 'catch'/'rescue' or 'finally'/'ensure' clause. Perl 5
lacks built-in structured exception handling. For Perl 6, RFC 88
proposes an exception mechanism that retains all the 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.
To keep things simpler, the C API calls for setting an exception
will not automatically set the exception's '__context__'. Guido
van Rossum has has expressed concerns with making such changes [8].
As for other languages, Java and Ruby both discard the original
exception when another exception occurs in a 'catch'/'rescue' or
'finally'/'ensure' clause. Perl 5 lacks built-in structured
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
may point to another exception. This property is not set by the VM
automatically. Instead, the constructors of exception objects all
accept an optional 'innerException' argument to explicitly set this
property. The C# documentation says "an exception that is thrown as
a direct result of a previous exception should include a reference
to the previous exception in the InnerException property."
may point to another exception [9]. According to its documentation,
"When an exception X is thrown as a direct result of a previous
exception Y, the InnerException property of X should contain a
reference to Y." This property is not set by the VM automatically;
rather, all exception constructors take an optional 'innerException'
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
one proposal is that the '__traceback__' attribute provides
@ -202,7 +209,11 @@ Explicit Exception Chaining
The '__cause__' attribute on exception objects is always initialized
to None. It is set by calling the 'setcause' method, a new 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
few different kinds of storage, with file storage as one kind. The
@ -301,12 +312,10 @@ Enhanced Reporting
C API
To keep things simpler, the PyErr_Set* calls for setting exceptions
will not set the '__context__' attribute on exceptions. The BDFL has
has expressed qualms with making such changes to PyErr_Set* [8].
PyErr_NormalizeException will always set the 'traceback' attribute
to its 'tb' argument and the '__context__' attribute to None.
The PyErr_Set* calls for setting exceptions will not set the
'__context__' attribute on exceptions. PyErr_NormalizeException
will always set the 'traceback' attribute to its 'tb' argument and
the '__context__' and '__cause__' attributes to None.
A new API function, PyErr_SetContext(context), will help C
programmers provide chained exception information. This function
@ -319,25 +328,28 @@ Compatibility
Chained exceptions expose the type of the most recent exception, so
they will still match the same 'except' clauses as they do now.
The proposed changes should not break any code except for code that
currently sets or depends on the values of attributes named
'__context__', '__cause__', or '__traceback__' on exception
instances. As of 2005-05-12, the Python standard library contains
no mention of such attributes.
The proposed changes should not break any code unless the code sets
or uses attributes named '__context__', '__cause__', 'setcause', or
'__traceback__' on exception instances. As of 2005-05-12, the
Python standard library contains no mention of such attributes.
Open Issues
Walter Dörwald [9] expressed a desire to attach extra information
to an exception during its upward propagation, without changing its
Walter Dörwald [10] expressed a desire to attach extra information
to an exception during its upward propagation without changing its
type. This could be a useful feature, but it is not addressed by
this PEP. It could conceivably be addressed by a separate PEP
establishing conventions for other informational attributes on
exceptions.
It is not clear whether the '__context__' feature proposed here would
be sufficient to cover all the use cases that Raymond Hettinger [1]
originally had in mind.
It is not clear whether the '__context__' and '__cause__' features
proposed here would be sufficient to cover all the use cases that
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;
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*
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