2

My issue is a design problem. I have the following Logger class:

import logging, logging.handlers

class Logger(object):
    def __init__(self, log_filename, name):
        self.LOG_FILENAME = log_filename

        logging.basicConfig(format='%(asctime)s %(message)s')
        formatter = logging.Formatter(
            '%(asctime)s - %(levelname)s - %(message)s')
        loghandler = logging.handlers.RotatingFileHandler(
            self.LOG_FILENAME)
        loghandler.setFormatter(formatter)
        self.logger = logging.getLogger(name)
        self.logger.setLevel(logging.INFO)
        self.logger.addHandler(loghandler)

    def getLogger(self):
        return self.logger

The context is the following, I have several modules that will make use of this class, every class is agnostic of the others or of the logger, so every class instantiates a new Logger class (even when they need to write to the same file), the problem is that if I have 2 classes that need to write to the same Logger, I get repeated lines, this reproduces the bug:

def a():
    log = Logger(log_filename='test.log', name='test')
    logger = log.getLogger()
    logger.info('A')

def b():
    log = Logger(log_filename='test.log', name='test')
    logger = log.getLogger()
    logger.info('B')

so if I call a() I will get what I'm expecting: 2014-12-02 10:26:40,665 - INFO - A, but if now I call b() i'll get:

2014-12-02 10:26:40,665 - INFO - A
2014-12-02 10:26:48,553 - INFO - B
2014-12-02 10:26:48,553 - INFO - B

and so on, I know Logger is a Singleton class, and the bug has to be in my Logger class, but I assumed that getLogger with the name of the logger would return the "same" logging class instance.

1 Answer 1

4

Your assumption is correct and is the cause for the problem. You're adding many handlers to the same logger here:

    self.logger = logging.getLogger(name) # <-- same logger for same "name"!
    self.logger.setLevel(logging.INFO)
    self.logger.addHandler(loghandler)

With each instantiation using the same name parameter (in your case in both calls):

    # same name!
def a():
    log = Logger(log_filename='test.log', name='test')
...
def b():
    log = Logger(log_filename='test.log', name='test')

the same logger gets more handlers.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.