On Fri, Jan 27, 2012 at 1:54 PM, Benjamin Peterson <benja...@python.org> wrote: > BTW, I don't really think this needs a PEP.
That's largely my influence - the discussion in the relevant tracker item (http://bugs.python.org/issue6210) had covered enough ground that I didn't notice that Ethan's specific proposal *isn't* a syntax change, but is rather just a matter of giving some additional semantics to the "raise X from Y" syntax (some of the other suggestions like "raise as <whatever>" really were syntax changes). So I've changed my mind to being +1 on the idea and proposed syntax of the draft PEP, but I think there are still some details to be worked through in terms of the detailed semantics. (The approach in Ethan's patch actually *clobbers* the context info when "from None" is used, and I don't believe that's a good idea. My own suggestions in the tracker item aren't very good either, for exactly the same reason) Currently, the raise from syntax is just syntactic sugar for setting __cause__ manually: >>> try: ... 1/0 ... except ZeroDivisionError as ex: ... new_exc = ValueError("Denominator is zero") ... new_exc.__cause__ = ex ... raise new_exc ... Traceback (most recent call last): File "<stdin>", line 2, in <module> ZeroDivisionError: division by zero The above exception was the direct cause of the following exception: Traceback (most recent call last): File "<stdin>", line 6, in <module> ValueError: Denominator is zero The context information isn't lost in that case, the display of it is simply suppressed when an explicit cause is set: >>> try: ... try: ... 1/0 ... except ZeroDivisionError as ex: ... new_exc = ValueError() ... new_exc.__cause__ = ex ... raise new_exc ... except ValueError as ex: ... saved = ex ... >>> saved.__context__ ZeroDivisionError('division by zero',) >>> saved.__cause__ ZeroDivisionError('division by zero',) This behaviour (i.e. preserving the context, but not displaying it by default) is retained when using the dedicated syntax: >>> try: ... try: ... 1/0 ... except ZeroDivisionError as ex: ... raise ValueError() from ex ... except ValueError as ex: ... saved = ex ... >>> saved.__context__ ZeroDivisionError('division by zero',) >>> saved.__cause__ ZeroDivisionError('division by zero',) However, if you try to set the __cause__ to None explicitly, then the display falls back to showing the context: >>> try: ... 1/0 ... except ZeroDivisionError as ex: ... new_exc = ValueError("Denominator is zero") ... new_exc.__cause__ = None ... raise new_exc ... Traceback (most recent call last): File "<stdin>", line 2, in <module> ZeroDivisionError: division by zero During handling of the above exception, another exception occurred: Traceback (most recent call last): File "<stdin>", line 6, in <module> ValueError: Denominator is zero This happens because None is used by the exception display logic to indicate "no specific cause, so report the context if that is set". My proposal would be that instead of using None as the "not set" sentinel value for __cause__, we instead use a dedicated sentinel object (exposed to Python at least as "BaseException().__cause__", but potentially being given its own name somewhere). Then the display logic for exceptions would be changed to be: - if the __cause__ is None, then don't report a cause or exception context at all - if the __cause__ is BaseException().__cause__, report the exception context (from __context__) - otherwise report __cause__ as the specific cause of the raised exception That way we make it easy to emit nicer default tracebacks when replacing exceptions without completely hiding the potentially useful data that can be provided by retaining information in __context__. I've been burnt by too much code that replaces detailed, informative and useful error messages that tell me exactly what is going wrong with bland, useless garbage to be in favour of an approach that doesn't even set the __context__ attribute in the first place. If __context__ is always set regardless, and then __cause__ is used to control whether or not __context__ gets displayed in the standard tracebacks, that's a much more flexible approach. Cheers, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia _______________________________________________ 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