1

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.getLogger('name')
logger.info('HI')

The expected output:

2014-09-29 10:50:40,187 - INFO - ** My prologue **
2014-09-29 10:50:40,187 - INFO - HI
2014-09-29 10:50:40,187 - INFO - ** My epilogue **
Ofer Helman
  • 714
  • 1
  • 8
  • 25

2 Answers2

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 :)

GreenAsJade
  • 14,459
  • 11
  • 63
  • 98
  • I have tried this, for some reason it does't always log the epilogue. I did like the link about singletons though and decided to take the problem to a different approach – Ofer Helman Sep 29 '14 at 20:59
  • Not sure yet why that would be, but I coded this quickly, with a light test only. I may tinker around out of curiousity when I get a moment. Most of my python is building wx apps, and I explicitly pass my logger around to the views & controller. – GreenAsJade Sep 29 '14 at 22:13
  • With expert help (http://stackoverflow.com/a/26119248/554807) I think I've found what would give you strife, and edited accordingly. I tested it more thoroughly (mutliple files, multiple loggers). I'd be keen to know if it works in your situation. Even though now the code is even more spooky :) That's singletons for you ;) – GreenAsJade Sep 30 '14 at 11:24
0

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)

GreenAsJade
  • 14,459
  • 11
  • 63
  • 98