96
votes

How can I log an exception in Python?

I've looked at some options and found out I can access the actual exception details using this code:

import sys
import traceback

try:
    1/0
except:
    exc_type, exc_value, exc_traceback = sys.exc_info()
    traceback.print_exception(exc_type, exc_value, exc_traceback)

I would like to somehow get the string print_exception() throws to stdout so that I can log it.

5
At least raise (without argument, so the stracktrace gets preserved) after logging, otherwise you swallow the exception silently. - user395760
You should always explicitly state the exception you are trying to catch: except NameError as e, say. That will prevent you catching things like KeyboardInterrupt and give you a reference to the exception object, which you can study for more details. - Katriel

5 Answers

48
votes

In Python 3.5 you can pass exception instance in exc_info argument:

import logging
try:
    1/0
except Exception as e:
   logging.error('Error at %s', 'division', exc_info=e)
137
votes

Take a look at logging.exception (Python Logging Module)

import logging 
def foo():
    try:
        some_code()
    except:
        logging.exception('')

This should automatically take care of getting the traceback for the current exception and logging it properly.

62
votes

To answer your question, you can get the string version of print_exception() using the traceback.format_exception() function. It returns the traceback message as a list of strings rather than printing it to stdout, so you can do what you want with it. For example:

import sys
import traceback

try:
    asdf
except NameError:
    exc_type, exc_value, exc_traceback = sys.exc_info()
    lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
    print ''.join('!! ' + line for line in lines)  # Log it or whatever here

This displays:

!! Traceback (most recent call last):
!!   File "<stdin>", line 2, in <module>
!! NameError: name 'asdf' is not defined

However, I'd definitely recommend using the standard Python logging module, as suggested by rlotun. It's not the easiest thing to set up, but it's very customizable.

53
votes

Logging exceptions is as simple as adding the exc_info=True keyword argument to any log message, see entry for Logger.debug in http://docs.python.org/2/library/logging.html.

Example:

try: 
    raise Exception('lala')
except Exception:
    logging.info('blah', exc_info=True)

output (depending, of course, on your log handler config):

2012-11-29 10:18:12,778 - root - INFO - <ipython-input-27-5af852892344> : 3 - blah
Traceback (most recent call last):
  File "<ipython-input-27-5af852892344>", line 1, in <module>
    try: raise Exception('lala')
Exception: lala
4
votes

First of all, consider using a proper Exception type on your except clause. Then, naming the exception, you can print it:

try:
    1/0
except Exception as e:
    print e

Dependending on your Python version, you must use

except Exception, e