Terry J. Reedy added the comment:

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)

None

In 3.?, value must be an exception instance (or compatible duck) (not 
documented).
...
  File "C:\Programs\Python36\lib\traceback.py", 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.

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue26389>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to