In my opinion using Ellipsis is just wrong. It is completely non-obvious not only to a beginner, but even to an experienced python developer. Writing 'raise Something() from None' looks less suspicious, but still strange.
Isn't 'raise Exception().no_context()' or 'raise Exception().no_cause()' more obvious and easy to implement? More readable, less complex and ambiguous. On 2012-02-02, at 5:10 PM, Ethan Furman wrote: > PEP: 409 > Title: Suppressing exception context > Version: $Revision$ > Last-Modified: $Date$ > Author: Ethan Furman <et...@stoneleaf.us> > Status: Draft > Type: Standards Track > Content-Type: text/x-rst > Created: 26-Jan-2012 > Post-History: 30-Aug-2002, 01-Feb-2012, 03-Feb-2012 > > > Abstract > ======== > > One of the open issues from PEP 3134 is suppressing context: currently > there is no way to do it. This PEP proposes one. > > > Rationale > ========= > > 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 (/ValueError/, /TypeError/, or > 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. > > > Alternatives > ============ > Several possibilities have been put forth: > > * /raise as NewException()/ > > Reuses the /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 > > * /raise NewException.no_context(...)/ > > Make context suppression a class method. > > All of the above options will require changes to the core. > > > Proposal > ======== > > 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 is not displayed > by the default exception printing routines. > > > Implementation Discussion > ========================= > > Currently, /None/ is the default for both /__context__/ and /__cause__/. > In order to support /raise ... from None/ (which would set /__cause__/ > to /None/) we need a different default value for /__cause__/. Several > ideas were put forth on how to implement this at the language level: > > * Overwrite the previous exception information (side-stepping the > issue and leaving /__cause__/ at /None/). > > Rejected as this can seriously hinder debugging due to > `poor error messages`_. > > * Use one of the boolean values in /__cause__/: /False/ would be the > default value, and would be replaced when /from .../ was used with > the explicity chained exception or /None/. > > Rejected as this encourages the use of two different objects types for > /__cause__/ with one of them (boolean) not allowed to have the full > range of possible values (/True/ would never be used). > > * Create a special exception class, /__NoException__/. > > Rejected as possibly confusing, possibly being mistakenly raised by > users, and not being a truly unique value as /None/, /True/, and > /False/ are. > > * Use /Ellipsis/ as the default value (the /.../ singleton). > > Accepted. There are no other possible values; it cannot be raised as > it is not an acception; it has the connotation of 'fill in the > rest...' as in /__cause__/ is not set, look in /__context__/ for it. > > > Language Details > ================ > > To support /from None/, /__context__/ will stay as it is, but > /__cause__/ will start out as /Ellipsis/ and will change to /None/ > when the /raise ... from None/ method is used. > > ============================== ================== ================== > form __context__ __cause__ > ============================== ================== ================== > raise /None/ /Ellipsis/ > > reraise previous exception /Ellipsis/ > > reraise from previous exception /None/ | > /None/ | /ChainedException/ explicitly chained > exception > ============================== ================== ================== > > The default exception printing routine will then: > > * If /__cause__/ is /Ellipsis/ the /__context__/ (if any) will be > printed. > > * If /__cause__/ is /None/ the /__context__/ will not be printed. > > * if /__cause__/ is anything else, /__cause__/ will be printed. > > > Patches > ======= > > There is a patch for CPython implementing this attached to `Issue 6210`_. > > > References > ========== > > Discussion and refinements in this `thread on python-dev`_. > > .. _poor 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 > > > Copyright > ========= > > This document has been placed in the public domain. > > _______________________________________________ > Python-Dev mailing list > Python-Dev@python.org > http://mail.python.org/mailman/listinfo/python-dev > Unsubscribe: > http://mail.python.org/mailman/options/python-dev/yselivanov.ml%40gmail.com _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com