Reputation: 9102
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.
Upvotes: 2
Views: 863
Reputation: 31339
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.
Upvotes: 4