Skip to content Skip to sidebar Skip to footer

Prologue And Epilogue In Python Logger

I wish to create a logger class that upon the first logging.getLogger() will write a prologue and once the process ends the logger with write an epilogue my code: logger = logging.

Solution 1:

As observed, the epiLoggers in my previous answers are not "singletons", and have to be passed around between modules that are going to use them.

Options for getting around this include

  • subclassing logger.Logger (if that is in fact possible, which I have not investigated),
  • implementing a mechanism to create and store and retrive epiLoggers like logger.getLogger (ridiculously overblown idea)
  • creating a singleton-like epiLogger that can be used in multiple modules.

This solution does the latter.

import logging

class epiLogger():
    _initialised = {}
    _finalised = {}

    def __init__(self, name):
        self.logger = logging.getLogger(name)
        self.name = name
        if not epiLogger._initialised.get(name):
            self.logger.addHandler(logging.StreamHandler())
            self.logger.setLevel(logging.INFO)
            self.logger.info('** My Prologue **')
            epiLogger._initialised[self.name] = True

    def info(self, the_info):
        self.logger.info(the_info)

    def __del__(self):
        if not self.__class__._finalised.get(self.name):
            self.logger.info('** My Epilogue **')
            self.__class__._finalised[self.name] = True

a = epiLogger("foo")

a.info("foo!")
a.info("bar!")
a.info("party!")

I know that this feels like a good thing to do, but read here: http://jalf.dk/blog/2010/03/singletons-solving-problems-you-didnt-know-you-never-had-since-1995/. I would seriously ask yourself "actually, might it be best in the long run to pass each epiLogger around to where it belongs?"

Or of course investigate subclassing logger.Logger :)


Solution 2:

Here is a brute force, simplistic implementation.

Note that any logging.Logger methods you want to call on the epiLogger need to be implemented: I've only implemented info().

import logging

# class definition for the new logger that does the pro and epilogues

class epiLogger():
    def __init__(self, name):
        self.logger = logging.getLogger(name)
        self.logger.info('** My Prologue **')

    def info(self, the_info):
        self.logger.info(the_info)

    def __del__(self):
        self.logger.info('** My Epilogue **')

# preamble to set up the underlying logger that it needs
# ... could be inside the class constructor, depending on whether the class
# is supposed to be "encapsulating and providing"  or "using" this external one

the_logger = logging.getLogger("foo")
the_logger.setLevel(logging.INFO)

the_logger.addHandler(logging.StreamHandler())

# using the good stuff...

a = epiLogger("foo")

a.info("foo!")
a.info("bar!")
a.info("party!")

produces:

~ mgregory$ python foo.py
** My Prologue **
foo!
bar!
party!
** My Epilogue **
~ mgregory$ 

(For simplicity I've left out the time/date formatting etc, since it's not really relevant to the question)


Post a Comment for "Prologue And Epilogue In Python Logger"