Search code examples
pythonloggingpython-logging

Replace default handler of Python logger


I've got the following code running on each request of a wsgi (web2py) application:

import logging, logging.handlers
from logging import StreamHandler, Formatter

def get_configured_logger(name):

    logger = logging.getLogger(name)

    if (len(logger.handlers) == 0):
        # This logger has no handlers, so we can assume it hasn't yet been configured (Django uses similiar trick)

        # === Configure logger ===

        # Create Formatted StreamHandler:
        FORMAT = "%(process)s %(thread)s: %(message)s"
        formatter = logging.Formatter(fmt=FORMAT)
        handler = logging.StreamHandler()
        handler.setFormatter(formatter)
        logger.addHandler(handler)
        logger.setLevel(logging.DEBUG)
        logger.debug('CONFIGURING LOGGER')

    return logger

# Get app specific logger:
logger = get_configured_logger(request.application)
logger.debug("TEST")

It's meant to configure the logger once, with the formatted handler I want. It works, except that I'm getting double entries in my stdout:

81893 4329050112: CONFIGURING LOGGER
DEBUG:dummy:CONFIGURING LOGGER
81893 4329050112: TEST
DEBUG:dummy:TEST

How do I use my new formatted handler and get rid of/hide the default one?


Solution

  • Perhaps the following example will help. Basically you can either remove the handlers of the logger you'd like to disable, or don't propagate with the logger you are logging from.

    $ cat testlog.py
    import logging
    logging.basicConfig(filename='foo', level=logging.DEBUG)
    root_logger = logging.getLogger()
    root_logger.debug('bar')
    
    my_logger = logging.getLogger('my_logger')
    FORMAT = "%(process)s %(thread)s: %(message)s"
    formatter = logging.Formatter(fmt=FORMAT)
    handler = logging.StreamHandler()
    handler.setFormatter(formatter)
    
    my_logger.addHandler(handler)
    my_logger.setLevel(logging.DEBUG)
    my_logger.info('baz')
    
    my_logger.propagate = False
    my_logger.info('foobar')
    
    my_logger.propagate = True
    my_logger.info('foobaz')
    root_logger.handlers = []
    my_logger.info('barbaz')
    
    $ python testlog.py
    5927 140735224465760: baz
    5927 140735224465760: foobar
    5927 140735224465760: foobaz
    5927 140735224465760: barbaz
    
    $ cat foo
    DEBUG:root:bar
    INFO:my_logger:baz
    INFO:my_logger:foobaz