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

后端 未结 15 2056
天命终不由人
天命终不由人 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 14:08

    traceback.format_exc() or sys.exc_info() will yield more info if that's what you want.

    import traceback
    import sys
    
    try:
        do_stuff()
    except Exception:
        print(traceback.format_exc())
        # or
        print(sys.exc_info()[2])
    
    0 讨论(0)
  • 2020-11-22 14:09

    You will need to put the try/except inside the most innerloop where the error may occur, i.e.

    for i in something:
        for j in somethingelse:
            for k in whatever:
                try:
                    something_complex(i, j, k)
                except Exception, e:
                    print e
            try:
                something_less_complex(i, j)
            except Exception, e:
                print e
    

    ... and so on

    In other words, you will need to wrap statements that may fail in try/except as specific as possible, in the most inner-loop as possible.

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

    If you have an Error object already, and you want to print the whole thing, you need to make this slightly awkward call:

    import traceback
    traceback.print_exception(type(err), err, err.__traceback__)
    

    That's right, print_exception takes three positional arguments: The type of the exception, the actual exception object, and the exception's own internal traceback property.

    In python 3.5 or later, the type(err) is optional... but it's a positional argument, so you still have to explicitly pass None in its place.

    traceback.print_exception(None, err, err.__traceback__)
    

    I have no idea why all of this isn't just traceback.print_exception(err). Why you would ever want to print out an error, along with a traceback other than the one that belongs to that error, is beyond me.

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

    First, don't use prints for logging, there is astable, proven and well-thought out stdlib module to do that: logging. You definitely should use it instead.

    Second, don't be tempted to do a mess with unrelated tools when there is native and simple approach. Here it is:

    log = logging.getLogger(__name__)
    
    try:
        call_code_that_fails()
    except MyError:
        log.exception('Any extra info you want to see in your logs')
    

    That's it. You are done now.

    Explanation for anyone who is interested in how things work under the hood

    What log.exception is actually doing is just a call to log.error (that is, log event with level ERROR) and print traceback then.

    Why is it better?

    Well, here is some considerations:

    • it is just right;
    • it is straightforward;
    • it is simple.

    Why should nobody use traceback or call logger with exc_info=True or get their hands dirty with sys.exc_info?

    Well, just because! They all exist for different purposes. For example, traceback.print_exc's output is a little bit different from tracebacks produced by the interpreter itself. If you use it, you will confuse anyone who reads your logs, they will be banging their heads against them.

    Passing exc_info=True to log calls is just inappropriate. But, it is useful when catching recoverable errors and you want to log them (using, e.g INFO level) with tracebacks as well, because log.exception produces logs of only one level - ERROR.

    And you definitely should avoid messing with sys.exc_info as much as you can. It's just not a public interface, it's an internal one - you can use it if you definitely know what you are doing. It is not intended for just printing exceptions.

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

    If you're debugging and just want to see the current stack trace, you can simply call:

    traceback.print_stack()

    There's no need to manually raise an exception just to catch it again.

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

    traceback.format_exception

    If you only have the exception object, you can get the traceback as a string from any point of the code in Python 3 with:

    import traceback
    
    ''.join(traceback.format_exception(None, exc_obj, exc_obj.__traceback__))
    

    Full example:

    #!/usr/bin/env python3
    
    import traceback
    
    def f():
        g()
    
    def g():
        raise Exception('asdf')
    
    try:
        g()
    except Exception as e:
        exc = e
    
    tb_str = ''.join(traceback.format_exception(None, exc_obj, exc_obj.__traceback__))
    print(tb_str)
    

    Output:

    Traceback (most recent call last):
      File "./main.py", line 12, in <module>
        g()
      File "./main.py", line 9, in g
        raise Exception('asdf')
    Exception: asdf
    

    Documentation: https://docs.python.org/3.7/library/traceback.html#traceback.format_exception

    See also: Extract traceback info from an exception object

    Tested in Python 3.7.3.

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