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

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

    How to print the full traceback without halting the program?

    When you don't want to halt your program on an error, you need to handle that error with a try/except:

    try:
        do_something_that_might_error()
    except Exception as error:
        handle_the_error(error)
    

    To extract the full traceback, we'll use the traceback module from the standard library:

    import traceback
    

    And to create a decently complicated stacktrace to demonstrate that we get the full stacktrace:

    def raise_error():
        raise RuntimeError('something bad happened!')
    
    def do_something_that_might_error():
        raise_error()
    

    Printing

    To print the full traceback, use the traceback.print_exc method:

    try:
        do_something_that_might_error()
    except Exception as error:
        traceback.print_exc()
    

    Which prints:

    Traceback (most recent call last):
      File "", line 2, in 
      File "", line 2, in do_something_that_might_error
      File "", line 2, in raise_error
    RuntimeError: something bad happened!
    

    Better than printing, logging:

    However, a best practice is to have a logger set up for your module. It will know the name of the module and be able to change levels (among other attributes, such as handlers)

    import logging
    logging.basicConfig(level=logging.DEBUG)
    logger = logging.getLogger(__name__)
    

    In which case, you'll want the logger.exception function instead:

    try:
        do_something_that_might_error()
    except Exception as error:
        logger.exception(error)
    

    Which logs:

    ERROR:__main__:something bad happened!
    Traceback (most recent call last):
      File "", line 2, in 
      File "", line 2, in do_something_that_might_error
      File "", line 2, in raise_error
    RuntimeError: something bad happened!
    

    Or perhaps you just want the string, in which case, you'll want the traceback.format_exc function instead:

    try:
        do_something_that_might_error()
    except Exception as error:
        logger.debug(traceback.format_exc())
    

    Which logs:

    DEBUG:__main__:Traceback (most recent call last):
      File "", line 2, in 
      File "", line 2, in do_something_that_might_error
      File "", line 2, in raise_error
    RuntimeError: something bad happened!
    

    Conclusion

    And for all three options, we see we get the same output as when we have an error:

    >>> do_something_that_might_error()
    Traceback (most recent call last):
      File "", line 1, in 
      File "", line 2, in do_something_that_might_error
      File "", line 2, in raise_error
    RuntimeError: something bad happened!
    

    Which to use

    Performance concerns aren't important here as IO usually dominates. I'd prefer, since it does precisely what's being requested in a forward compatible way:

    logger.exception(error)
    

    Logging levels and outputs can be adjusted, making it easy to turn off without touching the code. And usually doing what's directly needed is the most efficient way to do it.

提交回复
热议问题