[Python-Dev] Traceback behaviour in exceptional cases

Ka-Ping Yee ping@lfw.org
Tue, 2 May 2000 02:53:01 -0700 (PDT)


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