Python logger dynamic filename

How about simply wrap the handler code in a function:

import os
def myLogger(name):
    logger = logging.getLogger(name)
    logger.setLevel(logging.DEBUG)
    handler = logging.FileHandler(os.path.join('/some/path/', name + '.log'), 'w')
    logger.addHandler(handler)
    return logger

log_hm = myLogger('healthmonitor')
log_hm.info("Testing Log") # Should log to /some/path/healthmonitor.log

To prevent creating duplicate handlers, care needs to be taken to ensure that myLogger(name) is only called once per name. Usually that means putting myLogger(name) inside

if __name__ == '__main__':
    log_hm = myLogger('healthmonitor')

of the main script.


import os
import logging

class MyFileHandler(object):

    def __init__(self, dir, logger, handlerFactory, **kw):
        kw['filename'] = os.path.join(dir, logger.name)
        self._handler = handlerFactory(**kw)

    def __getattr__(self, n):
        if hasattr(self._handler, n):
            return getattr(self._handler, n)
        raise AttributeError, n

logger = logging.getLogger('test')
logger.setLevel(logging.INFO)
handler = MyFileHandler(os.curdir, logger, logging.FileHandler)
logger.addHandler(handler)
logger.info('hello mylogger')

The approach used in the above solution is correct, but that has issue of adding duplicate handlers when called more than once. Here is the improved version.

import os
def getLogger(name):
    # logger.getLogger returns the cached logger when called multiple times
    # logger.Logger created a new one every time and that avoids adding
    # duplicate handlers 
    logger = logging.Logger(name)
    logger.setLevel(logging.DEBUG)
    handler = logging.FileHandler(os.path.join('/some/path/', name + '.log'), 'a')
    logger.addHandler(handler)
    return logger

def test(i):
  log_hm = getLogger('healthmonitor')
  log_hm.info("Testing Log %s", i) # Should log to /some/path/healthmonitor.log

test(1)
test(2)

Tags:

Python

Logging