Welcome, guest | Sign In | My Account | Store | Cart

Pretty frequently I find myself needing to log my exceptions, and rather than produce a tangled mess of boilerplate code, I went ahead and put together this snippet to act as a base class for all those exceptions.

Python, 62 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#! /usr/bin/env python3

"""
selflogger.py

Written by Geremy Condra

Licensed under GPLv3

Released 27 May 2009

This module contains a simple exception
designed to self-log.
"""

import logging
import traceback

class LoggingError(Exception):
        """Basic logging error"""
        
        # set the logging options
        filename = 'log'
        datefmt = '%a, %d %b %Y %H:%M:%S'
        format = '%(asctime)s %(levelname)-8s %(message)s'
        
        # build the logger
        logging.basicConfig(level=logging.DEBUG,
                            filename=filename,
                            datefmt=datefmt,
                            format=format)

        # and get a local variable for it
        log = logging.getLogger('')
                
        def __init__(self, *args):
                # build the message from the user
                user_msg = args[0] if args else "An error has occurred"
                # get the traceback from the last error if it exists
                try: tb = traceback.format_exc()
                # otherwise, get the tb prior to this frame and pretend its us
                except: 
                        tb = "Traceback (most recent call last):\n"
                        tb += ''.join(traceback.format_stack()[:-1])
                        tb += self.__class__.__name__ + ": " + user_msg
                        tb += '\n'
                # build the complete log message
                log_msg = user_msg + "\n" + tb
                # and log it
                self.log.error(log_msg)
                # store the args
                self.args = args


if __name__ == "__main__":

        # example 1: raise it all by itself
        raise LoggingError("AIEEE!")

        # example 2: using it to log a re-raise
        try: dict()[5]
        except: raise LoggingError

3 comments

Sridhar Ratnakumar 14 years, 10 months ago  # | flag

Have you looked into Logger.exception?

Gabriel Genellina 14 years, 10 months ago  # | flag

Calling basicConfig from inside library code isn't nice - only the first call has any effect, and that should be reserved to application code.

Also, the exception should be logged when it is raised, not when it's created.

geremy condra (author) 14 years, 10 months ago  # | flag

@Sridhar Yes, I opted to do it this way so that both possibilities would be handled by my formatting code, which is somewhat different in use.