48

I want to check for errors in a particular background file, but the standard error stream is being controlled by the program in the foreground and the errors in the file in the question are not being displayed. I can use the logging module and write output to a file, though. I was wondering how I can use this to log all exceptions, errors and their tracebacks.

abc def foo bar
  • 2,360
  • 6
  • 30
  • 41
  • 5
    Possible duplicate of [Logging uncaught exceptions in Python](http://stackoverflow.com/questions/6234405/logging-uncaught-exceptions-in-python) – Trevor Boyd Smith Apr 06 '17 at 18:27

3 Answers3

91

It's probably a bad idea to log any exception thrown within the program, since Python uses exceptions also for normal control flow.

Therefore you should only log uncaught exceptions. You can easily do this using a logger's exception() method, once you have an exception object.

To handle all uncaught exceptions, you can either wrap your script's entry point in a try...except block, or by installing a custom exception handler by re-assigning sys.excepthook():

import logging
import sys

logger = logging.getLogger('mylogger')
# Configure logger to write to a file...

def my_handler(type, value, tb):
    logger.exception("Uncaught exception: {0}".format(str(value)))

# Install exception handler
sys.excepthook = my_handler

# Run your main script here:
if __name__ == '__main__':
    main()
Ferdinand Beyer
  • 64,979
  • 15
  • 154
  • 145
  • 6
    Isn't that good idea to append `sys.__excepthook__(type, value, tb)` to your `my_handler`, so it can process default actions on exception? – NG_ Jun 05 '14 at 15:55
  • 2
    @Ferdinand Beyer: Neat. Having `logger.exception("Uncaught exception: {0}: {1}".format(str(value.__class__.__name__), str(value)))` gives in my case `ERROR - Uncaught exception: IndexError: list index out of range` and prints for some reason `None`. How do i also get the full traceback? `tb` seems to be a traceback object but `traceback.print_tb(tb)` also just spits out `None`. – bioslime Oct 09 '14 at 16:09
  • 6
    @bioslime see [this recipe](http://stackoverflow.com/a/16993115/512111) which relies on the `exc_info` kwarg to log the traceback, too. It seems to only work with `logger.error` or `logger.critical`, but not with `logger.exception`. – j08lue Jul 22 '16 at 08:37
  • 1
    The above code does not work for me. Replacing `main()` with `hello ==== "Hello"` still results in a stack trace being printed to the console. – cclauss Sep 29 '19 at 05:07
  • This answer doesn't actually answer the question and while OP might have been satisfied, people coming from google may not be. There are valid reasons to want to log **all** raised exceptions even if they were caught by something. – RuRo Apr 19 '20 at 06:06
  • 5
    I prefer this answer too:http://stackoverflow.com/a/16993115/512111 – Zhou Hongbo Jul 03 '20 at 03:09
3
import sys
import logging
import traceback

# log uncaught exceptions
def log_exceptions(type, value, tb):
    for line in traceback.TracebackException(type, value, tb).format(chain=True):
        logging.exception(line)
    logging.exception(value)

    sys.__excepthook__(type, value, tb) # calls default excepthook

sys.excepthook = log_exceptions
JeffCharter
  • 1,431
  • 17
  • 27
3

Inspired of the main answer + How to write to a file, using the logging Python module? + Print original exception in excepthook, here is how to write the full traceback into a file test.log, like it would be printed in the console:

import logging, sys, traceback
logger = logging.getLogger('logger')
fh = logging.FileHandler('test.log')
logger.addHandler(fh)
def exc_handler(exctype, value, tb):
    logger.exception(''.join(traceback.format_exception(exctype, value, tb)))
sys.excepthook = exc_handler
print("hello")
1/0
Basj
  • 41,386
  • 99
  • 383
  • 673