How to catch and print the full exception traceback without halting/exiting the program?

后端 未结 15 2054
天命终不由人
天命终不由人 2020-11-22 13:46

I want to catch and log exceptions without exiting, e.g.,

try:
    do_stuff()
except Exception, err:
    print(Exception, err)
    # I want to print the entir         


        
相关标签:
15条回答
  • 2020-11-22 13:58

    python 3 solution

    stacktrace_helper.py

    from linecache import getline
    import sys
    import traceback
    
    
    def get_stack_trace():
        exc_type, exc_value, exc_tb = sys.exc_info()
        trace = traceback.format_stack()
        trace = list(filter(lambda x: ("\\lib\\" not in x and "/lib/" not in x and "stacktrace_helper.py" not in x), trace))
        ex_type = exc_type.__name__
        ex_line = exc_tb.tb_lineno
        ex_file = exc_tb.tb_frame.f_code.co_filename
        ex_message = str(exc_value)
        line_code = ""
        try:
            line_code = getline(ex_file, ex_line).strip()
        except:
            pass
    
        trace.insert(
            0, f'File "{ex_file}", line {ex_line}, line_code: {line_code} , ex: {ex_type} {ex_message}',
        )
        return trace
    
    
    def get_stack_trace_str(msg: str = ""):
        trace = list(get_stack_trace())
        trace_str = "\n".join(list(map(str, trace)))
        trace_str = msg + "\n" + trace_str
        return trace_str
    
    
    0 讨论(0)
  • 2020-11-22 13:59

    This is my solution to write the error in a log file and also on console:

    import logging, sys
    import traceback
    logging.basicConfig(filename='error.log', level=logging.DEBUG)
    
    def handle_exception(exc_type, exc_value, exc_traceback):
        import sys
        if issubclass(exc_type, KeyboardInterrupt):
            sys.__excepthook__(exc_type, exc_value, exc_traceback)
            return
        exc_info=(exc_type, exc_value, exc_traceback)
        logging.critical("\nDate:" + str(datetime.datetime.now()), exc_info=(exc_type, exc_value, exc_traceback))
        print("An error occured, check error.log to see the error details")
        traceback.print_exception(*exc_info)
    
    
    sys.excepthook = handle_exception
    
    0 讨论(0)
  • 2020-11-22 14:02

    You want the traceback module. It will let you print stack dumps like Python normally does. In particular, the print_last function will print the last exception and a stack trace.

    0 讨论(0)
  • 2020-11-22 14:04

    In addition to @Aaron Hall's answer, if you are logging, but don't want to use logging.exception() (since it logs at the ERROR level), you can use a lower level and pass exc_info=True. e.g.

    try:
        do_something_that_might_error()
    except Exception:
        logger.info('General exception noted.', exc_info=True)
    
    0 讨论(0)
  • 2020-11-22 14:05

    A remark about this answer's comments: print(traceback.format_exc()) does a better job for me than traceback.print_exc(). With the latter, the hello is sometimes strangely "mixed" with the traceback text, like if both want to write to stdout or stderr at the same time, producing weird output (at least when building from inside a text editor and viewing the output in the "Build results" panel).

    Traceback (most recent call last):
    File "C:\Users\User\Desktop\test.py", line 7, in
    hell do_stuff()
    File "C:\Users\User\Desktop\test.py", line 4, in do_stuff
    1/0
    ZeroDivisionError: integer division or modulo by zero
    o
    [Finished in 0.1s]

    So I use:

    import traceback, sys
    
    def do_stuff():
        1/0
    
    try:
        do_stuff()
    except Exception:
        print(traceback.format_exc())
        print('hello')
    
    0 讨论(0)
  • 2020-11-22 14:07

    To get the precise stack trace, as a string, that would have been raised if no try/except were there to step over it, simply place this in the except block that catches the offending exception.

    desired_trace = traceback.format_exc(sys.exc_info())
    

    Here's how to use it (assuming flaky_func is defined, and log calls your favorite logging system):

    import traceback
    import sys
    
    try:
        flaky_func()
    except KeyboardInterrupt:
        raise
    except Exception:
        desired_trace = traceback.format_exc(sys.exc_info())
        log(desired_trace)
    

    It's a good idea to catch and re-raise KeyboardInterrupts, so that you can still kill the program using Ctrl-C. Logging is outside the scope of the question, but a good option is logging. Documentation for the sys and traceback modules.

    0 讨论(0)
提交回复
热议问题