0

I am discovering logging and I would like to integrate it inside a class for external usage. It means, the user can either choose to ignore the logging feature or bind an handler to it.

I currently have this in my test module:

import logging
class Test:
   def __init__(self):
      self.logger = logging.getlogger(__module__ + '.Test')

   def hello(self):
      self.logger.warn('Hello World!')


test = Test()
test.hello()

With this I get the error

No handlers could be found for logger

I precisely don't want to bind a handler to this logger otherwise I may override the choice of the parent. I thought the default handler was Nullhandler.

What would be the correct pattern to integrate a logging feature inside an independant module?

Of course one solution would be to check if no handlers are binded to it:

if not len(self.logger): l.addHandler(logging.NullHandler())
nowox
  • 25,978
  • 39
  • 143
  • 293
  • This can't possibly be the real code. `Test` has no attribute `warn`. `self.warn('Hello World!')` would fail. – Peter Wood Nov 04 '15 at 20:52
  • @PeterWood my mistake :( – nowox Nov 04 '15 at 20:53
  • I created a wrapper module for the logging module that provides my own getLogger function that checks "if not logger.handlers" and adds a console handler. So your suggested solution should work. –  Nov 04 '15 at 20:55
  • @DavidCullen It should yes, but I am wondering if this is the proper solution. Adding logging capabilities to Python modules should be a very common need which would correspond to a well known design pattern. I am actually looking for it – nowox Nov 04 '15 at 21:00
  • This question shows what happens when module writers add logging to their modules: http://stackoverflow.com/questions/11029717/how-do-i-disable-log-messages-from-the-requests-library. People immediately start looking for ways to turn off the logging. So it might not be as common as you think. –  Nov 04 '15 at 21:08
  • Interesting. This would advise me to disable the logger by default which is not a bad idea :) – nowox Nov 04 '15 at 21:17

1 Answers1

1

This is what I use in one of my projects.

def get_logger(log_level,log_name='YourNameGoesHere'):
    logger = logging.getLogger(log_name)
    if not logger.handlers:
        logger.setLevel(log_level)
        ch = logging.StreamHandler()
        ch.setLevel(log_level)
        ch.setFormatter(logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
        ))
        logger.addHandler(ch)
        logger.propagate = 0
    return logger
RobertB
  • 1,879
  • 10
  • 17