How to log exceptions in Python

python
Published

October 1, 2013

Sometimes it is useful to just catch any exception, write details to a log file and continue execution.

In the Python standard library, it is possible to use the logging and exceptions modules to achieve this. First of all, we want to catch any exception, but also being able to access all information about it:

try:
    my_function_1()
except exception.Exception as e:
    print e.__class__, e.__doc__, e.message

Then we want to write those to a logging file, so we need to setup the logging module:

import logging
logging.basicConfig( filename="main.log",
                     filemode='w',
                     level=logging.DEBUG,
                     format= '%(asctime)s - %(levelname)s - %(message)s',
                   )

In the following gist everything together, with also function name detection from Alex Martelli:

import sys
import traceback
import logging
def setup_logging_to_file(filename):
logging.basicConfig( filename=filename,
filemode='w',
level=logging.DEBUG,
format= '%(asctime)s - %(levelname)s - %(message)s',
)
def extract_function_name():
"""Extracts failing function name from Traceback
by Alex Martelli
http://stackoverflow.com/questions/2380073/\
how-to-identify-what-function-call-raise-an-exception-in-python
"""
tb = sys.exc_info()[-1]
stk = traceback.extract_tb(tb, 1)
fname = stk[0][3]
return fname
def log_exception(e):
logging.error(
"Function {function_name} raised {exception_class} ({exception_docstring}): {exception_message}".format(
function_name = extract_function_name(), #this is optional
exception_class = e.__class__,
exception_docstring = e.__doc__,
exception_message = e.message))
import exceptions
import sys, os
from logging_utils import setup_logging_to_file, log_exception
from my_module import my_function_1, my_function_2
if __name__ == "__main__":
setup_logging_to_file("main.log")
try:
my_function_1()
except exceptions.Exception as e:
# we do not want to stop execution, just log and continue
log_exception(e)
try:
my_function_2()
except exceptions.Exception as e:
log_exception(e)
def my_function_1_wrapper():
my_function_1()
# in this case the log message is logging the wrapper as function name
try:
my_function_1_wrapper()
except exceptions.Exception as e:
log_exception(e)
view raw main.py hosted with ❤ by GitHub
import exceptions
class MyException(exceptions.Exception):
"""This is my own Exception"""
def my_function_1():
raise exceptions.IndexError("Some indexing error")
def my_function_2():
e = MyException("Something went quite wrong")
raise e
view raw my_module.py hosted with ❤ by GitHub

Here the output log:

2013-10-01 11:32:56,466 - ERROR - Function my_function_1() raised <type 'exceptions.IndexError'> (Sequence index out of range.): Some indexing error
2013-10-01 11:32:56,466 - ERROR - Function my_function_2() raised <class 'my_module.MyException'> (This is my own Exception): Something went quite wrong
2013-10-01 11:32:56,466 - ERROR - Function my_function_1_wrapper() raised <type 'exceptions.IndexError'> (Sequence index out of range.): Some indexing error