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
="main.log",
logging.basicConfig( filename='w',
filemode=logging.DEBUG,
levelformat= '%(asctime)s - %(levelname)s - %(message)s',
)
In the following gist everything together, with also function name detection from Alex Martelli:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
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