[Python-checkins] python/nondist/peps pep-0344.txt,NONE,1.1

ping@users.sourceforge.net ping at users.sourceforge.net
Sun May 15 21:30:41 CEST 2005


Update of /cvsroot/python/python/nondist/peps
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18411
Added Files:
	pep-0344.txt 
Log Message:
Add PEP 344: Exception Chaining and the Traceback Attribute.
--- NEW FILE: pep-0344.txt ---
PEP: 344
Title: Exception Chaining and the Traceback Attribute
Version: $Revision: 1.1 $
Last-Modified: $Date: 2005年05月15日 19:30:38 $
Author: Ka-Ping Yee
Status: Active
Type: Standards Track
Content-Type: text/plain
Created: 12-May-2005
Python-Version: 2.5
Abstract
 This PEP proposes two standard attributes on exception instances:
 the 'context' attribute for chained exceptions, and the 'traceback'
 attribute for the traceback.
Motivation
 Sometimes, during the handling of one exception (exception A),
 another exception (exception B) can occur. In today's Python
 (version 2.4), if this happens, exception B is propagated outward
 and exception A is lost. But in order to debug the problem, it is
 useful to know about both exceptions. The 'context' attribute
 retains this information.
 In today's Python implementation, exceptions are composed of three
 parts: the type, the value, and the traceback. The 'sys' module,
 exposes the current exception in three parallel variables, exc_type,
 exc_value, and exc_traceback, the sys.exc_info() function returns a
 tuple of these three parts, and the 'raise' statement has a
 three-argument form accepting these three parts. Manipulating
 exceptions often requires passing these three things in parallel,
 which can be tedious and error-prone. Additionally, the 'except'
 statement can only provide access to the value, not the traceback.
 Adding the 'traceback' attribute to exception values makes all the
 exception information accessible from a single place.
 The reason both of these attributes are presented together in one
 proposal is that the 'traceback' attribute provides convenient
 access to the traceback on chained exceptions.
History
 Raymond Hettinger [1] raised the issue of masked exceptions on
 Python-Dev in January 2003 and proposed a PyErr_FormatAppend()
 function that C modules could use to augment the currently active
 exception with more information.
 Brett Cannon [2] brought up chained exceptions again in June 2003
 and a long discussion followed. Other suggested attribute names
 include 'cause', 'antecedent', 'reason', 'original', 'chain',
 'chainedexc', 'exc_chain', 'excprev', 'previous', and 'precursor'.
 This PEP suggests 'context' because the intended meaning is more
 specific than temporal precedence and less specific than causation:
 an exception occurs in the *context* of handling another exception.
 Greg Ewing [3] identified the case of an exception occuring in a
 'finally' block during unwinding triggered by an original exception,
 as distinct from the case of an exception occuring in an 'except'
 block that is handling the original exception. This PEP handles
 both situations in the same way; it is assumed to be unnecessary to
 add mechanisms for distinguishing them since the programmer can tell
 them apart by reading the traceback.
 Greg Ewing [4] and Guido van Rossum [5], and probably others, have
 previously mentioned adding the traceback attribute to Exception
 instances. This is noted in PEP 3000.
 This PEP was motivated by yet another recent Python-Dev reposting
 of the same ideas [6] [7].
*** Add rationale for: choice of name, handling both finally/except,
 handling finally/except the same, displaying outermost last.
*** Compare to Java: exceptions are lost in catch or finally clauses.
*** Compare to Ruby: exceptions are lost just like Java.
*** Compare to C#:
*** Compare to E:
*** COmpare to Perl: RFC 88 a mess.
*** Note http://pclt.cis.yale.edu/pclt/exceptions.htm
Exception Chaining
 Here is an example to illustrate the 'context' attribute.
 def compute(a, b):
 try:
 a/b
 except Exception, exc:
 log(exc)
 def log(exc):
 file = open('logfile.txt') # oops, forgot the 'w'
 print >>file, exc
 file.close()
 Calling compute(0, 0) causes a ZeroDivisionError. The compute()
 function catches this exception and calls log(exc), but the log()
 function also raises an exception when it tries to write to a
 file that wasn't opened for writing.
 In today's Python, the caller of compute() gets thrown an IOError.
 The ZeroDivisionError is lost. With the proposed change, the
 instance of IOError has an additional 'context' attribute that
 retains the ZeroDivisionError.
 The following more elaborate example demonstrates the handling of a
 mix of 'finally' and 'except' clauses:
 def main(filename):
 file = open(filename) # oops, forgot the 'w'
 try:
 try:
 compute()
 except Exception, exc:
 log(file, exc)
 finally:
 file.clos() # oops, misspelled 'close'
 
 def compute():
 1/0
 
 def log(file, exc):
 try:
 print >>file, exc # oops, file is not writable
 except:
 display(exc)
 
 def display(exc):
 print ex # oops, misspelled 'exc'
 Calling main() with the name of an existing file will trigger four
 exceptions. The ultimate result will be an AttributeError due to
 the misspelling of 'clos', which has a context attribute pointing to
 a NameError due to the misspelling of 'ex', which has a context
 attribute pointing to an IOError due to the file being read-only,
 which has a context attribute pointing to a ZeroDivisionError, which
 has a context attribute of None.
 The proposed semantics are as follows:
 1. Each thread has an exception context initially set to None.
 
 2. Whenever an exception is raised, if the exception instance does
 not already have a 'context' attribute, the interpreter sets it
 equal to the thread's exception context.
 3. Immediately after an exception is raised, the thread's exception
 context is set to the exception.
 4. Whenever the interpreter exits an 'except' block by reaching the
 end or executing a 'return', 'yield', 'continue', or 'break'
 statement, the thread's exception context is set to None.
Traceback Attribute
 The following example illustrates the 'traceback' attribute.
 def do_logged(file, work):
 try:
 work()
 except Exception, exc:
 write_exception(file, exc)
 raise exc
 from traceback import format_tb
 def write_exception(file, exc):
 ...
 type = exc.__class__
 message = str(exc)
 lines = format_tb(exc.traceback)
 file.write(... type ... message ... lines ...)
 ...
 In today's Python, the do_logged() function would have to extract
 the traceback from sys.exc_traceback or sys.exc_info()[2] and pass
 both the value and the traceback to write_exception(). With the
 proposed change, write_exception() simply gets one argument and
 obtains the exception using the 'traceback' attribute.
 The proposed semantics are as follows:
 1. Whenever an exception is raised, if the exception instance does
 not already have a 'traceback' attribute, the interpreter sets
 it to the newly raised traceback.
Enhanced Reporting
 The default exception handler will be modified to report chained
 exceptions. In keeping with the chronological order of tracebacks,
 the most recently raised exception is displayed last. The display
 begins with the description of the innermost exception and backs
 up the chain to the outermost exception. The tracebacks are
 formatted as usual, with the following line between tracebacks:
 During handling of the above exception, another exception occurred:
 In the 'traceback' module, the format_exception, print_exception,
 print_exc, and print_last functions will be updated to accept an
 optional 'context' argument, True by default. When this argument is
 True, these functions will format or display the entire chain of
 exceptions as just described. When it is False, these functions
 will format or display only the outermost exception.
 The 'cgitb' module will be updated to display the entire chain of
 exceptions.
C API
 To keep things simpler, the PyErr_Set* calls for setting exceptions
 will not set the 'context' attribute on exceptions. Guido van Rossum
 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.
 A new API function, PyErr_SetContext(context), will help C
 programmers provide chained exception information. This function
 will first normalize the current exception so it is an instance,
 then set its 'context' attribute.
Compatibility
 Chained exceptions expose their outermost type so that they will
 continue to match the same 'except' clauses as they do now.
 The proposed changes should not break any code except for code
 that currently sets and relies on the values of attributes named
 'context' or 'traceback' on exceptions.
 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
 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.
 The exception context is lost when a 'yield' statement is executed;
 resuming the frame after the 'yield' does not restore the context.
 This is not a new problem, as demonstrated by the following example:
 >>> def gen():
 ... try:
 ... 1/0
 ... except:
 ... yield 3
 ... raise
 ...
 >>> g = gen()
 >>> g.next()
 3
 >>> g.next()
 TypeError: exceptions must be classes, instances, or strings
 (deprecated), not NoneType
 For now, addressing this problem is out of the scope of this PEP.
Possible Future Compatible Changes
 These changes are consistent with the appearance of exceptions as
 a single object rather than a triple at the interpreter level.
 - Deprecating sys.exc_type, sys.exc_value, sys.exc_traceback, and
 sys.exc_info() in favour of a single member, sys.exception.
 - Deprecating sys.last_type, sys.last_value, and sys.last_traceback
 in favour of a single member, sys.last_exception.
 - Deprecating the three-argument form of the 'raise' statement in
 favour of the one-argument form.
 - Upgrading cgitb.html() to accept a single value as its first
 argument as an alternative to a (type, value, traceback) tuple.
Possible Future Incompatible Changes
 These changes might be worth considering for Python 3000.
 - Removing sys.exc_type, sys.exc_value, sys.exc_traceback, and
 sys.exc_info().
 - Removing sys.last_type, sys.last_value, and sys.last_traceback.
 - Replacing the three-argument sys.excepthook with a one-argument
 API, and changing the 'cgitb' module to match.
 - Removing the three-argument form of the 'raise' statement.
 - Upgrading traceback.print_exception to accept an 'exception'
 argument instead of the type, value, and traceback arguments.
Acknowledgements
 Brett Cannon, Greg Ewing, Guido van Rossum, Jeremy Hylton, Phillip
 J. Eby, Raymond Hettinger, Walter Dörwald, and others.
References
 [1] Raymond Hettinger, "Idea for avoiding exception masking"
 http://mail.python.org/pipermail/python-dev/2003-January/032492.html
 [2] Brett Cannon explains chained exceptions
 http://mail.python.org/pipermail/python-dev/2003-June/036063.html
 [3] Greg Ewing points out masking caused by exceptions during finally
 http://mail.python.org/pipermail/python-dev/2003-June/036290.html
 [4] Greg Ewing suggests storing the traceback in the exception object
 http://mail.python.org/pipermail/python-dev/2003-June/036092.html
 [5] Guido van Rossum mentions exceptions having a traceback attribute
 http://mail.python.org/pipermail/python-dev/2005-April/053060.html
 [6] Ka-Ping Yee, "Tidier Exceptions"
 http://mail.python.org/pipermail/python-dev/2005-May/053671.html
 [7] Ka-Ping Yee, "Chained Exceptions"
 http://mail.python.org/pipermail/python-dev/2005-May/053672.html
 [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
 http://mail.python.org/pipermail/python-dev/2003-June/036148.html
Copyright
 This document has been placed in the public domain.


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /