This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author terry.reedy
Recipients brett.cannon, martin.panter, mbussonn, terry.reedy
Date 2017-02-27.20:49:36
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <>
The print_exception API goes back to when exception values were (or at least, could be) strings.  Its doc is incomplete as to the requirements on the args and, at least by 3.5, erroneous.  To modify it, we need to understand how it actually works now.

In 2.7, 'etype' can apparently by anything with an __str__ method.  (Someone could check the 2.7 code.) At least Exception, 'abc', and None result in 'Exception', 'abc' or 'None' leading the last line.  Example:
>>> try: 1/0
except Exception as e:
	tb.print_exception(None, e, None)

None: integer division or modulo by zero

By at least 3.5, the etype arg can definitely be anything, because it is ignored.  The printed exception type is already grabbed from the exception. Any patch should not change this.  Note that this 3.x change already introduced an incompatibility.  In 3.5, the above prints 'ZeroDivisionError' instead of 'None'.

This holdover line in the doc "prints the exception etype and value after the stack trace" is wrong and should be corrected with a 'changed in 3.x' note if done after 3.0.  

In 2.7, value can at least be an exception, a string, or None (not documented).  (Ditto for checking the code.)

>>> try: 1/0
except Exception as e:
	tb.print_exception(None, 'zero-divive', tb=None)

None: zero-divive
>>> try: 1/0
except Exception as e:
	tb.print_exception(None, None, None)


In 3.?, value must be an exception instance (or compatible duck) (not documented).
  File "C:\Programs\Python36\lib\", line 465, in __init__
    if (exc_value and exc_value.__cause__ is not None
AttributeError: 'str' object has no attribute '__cause__'

So, more potential incompatibilities with 2.x.

In 2.7, tb is needed to supply the traceback, or to suppress it.  As a separate parameter, it allows a traceback to be modified before printing.*  The option of a modified or omitted traceback (the ultimate modification) should be kept.

*IDLE edits tracebacks before printing to delete artifacts introduced by IDLE internals.  The attempt is to print what the console interpreter would.  I don't currently know whether it replaces the original on the exception or not.  There is also a proposal for the standard interpreter to edit tracebacks after recursion limit exceptions.  So traceback editing is useful, and I see no need to force replacement of the semi-private e.__traceback__.

My suggestions:

tb: In 3.7, in the API, change 'tb' to 'tb=True'.  If tb is left True, grab it from the exception.  If tb is explicitly supplied, use it.  If tb is set to False or (for back compatibility) None, suppress it. 

value: In 3.5+ document that it must be an exception.
(Optional) Change 'value' to 'exc' in the API to reflect the 3.x restriction. Document 'value' as a deprecated synonym for keyword usage. Keep the synonym until after 2.7. 

etype: In 3.5+ document that it is an ignored dummy argument and that one can just pass 0, '', or None.
(Optional) Deprecate the parameter and make it optional.  This can be handled* in the code and would be like range having option 'start'.  This is messy but would be temporary.  Remove after 2.7.

* 1 arg = exc/value, 3 args are etype, value, tb, 2 args are exc, tb or etype, exc depending on whether the type(first) is BaseException.

I am inclined to go with both options, but even if the 3 of us agree, I might be inclined to post our intention on pydev.
Date User Action Args
2017-02-27 20:49:37terry.reedysetrecipients: + terry.reedy, brett.cannon, martin.panter, mbussonn
2017-02-27 20:49:37terry.reedysetmessageid: <>
2017-02-27 20:49:37terry.reedylinkissue26389 messages
2017-02-27 20:49:36terry.reedycreate