Mailing List Archive

Traceback behaviour in exceptional cases
Here is how i was planning to take care of exceptions in
sys.displaytb...


1. When the 'sys' module does not contain a 'stderr'
attribute, Python currently prints 'lost sys.stderr'
to the original stderr instead of printing the traceback.
I propose that it proceed to try to print the traceback
to the real stderr in this case.

2. If 'sys.stderr' is buffered, the traceback does not
appear in the file. I propose that Python flush
'sys.stderr' immediately after printing a traceback.

3. Tracebacks get printed to whatever object happens to
be in 'sys.stderr'. If the object is not a file (or
other problems occur during printing), nothing gets
printed anywhere. I propose that Python warn about
this on stderr, then try to print the traceback to
the real stderr as above.

4. Similarly, 'sys.displaytb' may cause an exception.
I propose that when this happens, Python invoke its
default traceback printer to print the exception from
'sys.displaytb' as well as the original exception.

#4 may seem a little convoluted, so here is the exact logic
i suggest (described here in Python but to be implemented in C),
where 'handle_exception()' is the routine the interpreter uses
to handle an exception, 'print_exception' is the built-in
exception printer currently implemented in PyErr_PrintEx and
PyTraceBack_Print, and 'err' is the actual, original stderr.

def print_double_exception(tb, exc, disptb, dispexc, file):
file.write("Exception occured during traceback display:\n")
print_exception(disptb, dispexc, file)
file.write("\n")
file.write("Original exception passed to display routine:\n")
print_exception(tb, exc, file)

def handle_double_exception(tb, exc, disptb, dispexc):
if hasattr(sys, 'stderr'):
err.write("Missing sys.stderr; printing exception to stderr.\n")
print_double_exception(tb, exc, disptb, dispexc, err)
return
try:
print_double_exception(tb, exc, disptb, dispexc, sys.stderr)
except:
err.write("Error on sys.stderr; printing exception to stderr.\n")
print_double_exception(tb, exc, disptb, dispexc, err)

def handle_exception():
tb, exc = sys.exc_traceback, sys.exc_value
try:
sys.displaytb(tb, exc)
except:
disptb, dispexc = sys.exc_traceback, sys.exc_value
try:
handle_double_exception(tb, exc, disptb, dispexc)
except: pass

def default_displaytb(tb, exc):
if hasattr(sys, 'stderr'):
print_exception(tb, exc, sys.stderr)
else:
print "Missing sys.stderr; printing exception to stderr."
print_exception(tb, exc, err)

sys.displaytb = sys.__displaytb__ = default_displaytb



-- ?!ng

"In the sciences, we are now uniquely privileged to sit side by side
with the giants on whose shoulders we stand."
-- Gerald Holton