PEP: 409 Title: Suppressing exception context Version: $Revision$ Last-Modified: $Date$ Author: Ethan Furman email@example.com Status: Draft Type: Standards Track Content-Type: text/x-rst Created: 26-Jan-2012 Post-History: 30-Aug-2002, 01-Feb-2012
One of the open issues from PEP 3134 is suppressing context: currently there is no way to do it. This PEP proposes one.
There are two basic ways to generate exceptions:
1) Python does it (buggy code, missing resources, ending loops, etc.)
2) manually (with a raise statement)
When writing libraries, or even just custom classes, it can become necessary to raise exceptions; moreover it can be useful, even necessary, to change from one exception to another. To take an example from my dbf module::
try: value = int(value) except Exception: raise DbfError(...)
Whatever the original exception was (
something else) is irrelevant. The exception from this point on is a
DbfError, and the original exception is of no value. However, if
this exception is printed, we would currently see both.
Several possibilities have been put forth:
raise as NewException()
as keyword; can be confusing since we are not really
reraising the originating exception
raise NewException() from None
Follows existing syntax of explicitly declaring the originating exception
exc = NewException(); exc.__context__ = None; raise exc
Very verbose way of the previous method
Make context suppression a class method.
All of the above options will require changes to the core.
I proprose going with the second option::
raise NewException from None
It has the advantage of using the existing pattern of explicitly setting the cause::
raise KeyError() from NameError()
but because the 'cause' is
None the previous context, while retained,
is not displayed by the default exception printing routines.
__cause__ start out as None, and
set as exceptions occur.
__context__ will stay as it is, but
__cause__ will start out as
False, and will change to
raise ... from None method is used.
The default exception printing routine will then:
any) will be
not be printed.
__cause__ is anything else,
__cause__ will be
This has the benefit of leaving the
__context__ intact for future
logging, querying, etc., while suppressing its display if it is not caught.
This is important for those times when trying to debug poorly written
bad error messages_.
There is a patch for CPython implementing this attached to
Discussion and refinements in this
thread on python-dev_.
.. _bad error messages: http://bugs.python.org/msg152294 .. _Issue 6210: http://bugs.python.org/issue6210 .. _thread on python-dev: http://mail.python.org/pipermail/python-dev/2012-January/115838.html
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 coding: utf-8 End: