pythonlogging

Change log level of a handler in a logger with multiple handlers


I am struggling with python logging library.
I want a custom logger with 2 handlers (one stream handler and one file handler) and one of them with a customizable log level. I can obtain what I want if I create everything in my main script, but everything fails if I create the logger as a class, in a separate module.
I have the logger class in a custom module, let's say logUtils.py, as follow

#imports...

class ColoredFormatter(logging.Formatter):
    #formatter definition

class MyLogger(logging.Logger):
    def __init__(self, name):
        logging.Logger.__init__(self, name, logging.DEBUG)
        color_formatter = ColoredFormatter()

        # this handler should be always at lowest level                                                                                                       
        fh = logging.FileHandler('test.log')
        fh.setLevel(logging.DEBUG)
        # this handler is at INFO level by default but can change (see next)                                                                                                    
        ch = logging.StreamHandler()
        ch.setLevel(logging.INFO)
        # add formatter to the handlers                                                                                                                       
        fh.setFormatter(color_formatter)
        ch.setFormatter(color_formatter)
        # add the handlers to logger                                                                                                                          
        self.addHandler(fh)
        self.addHandler(ch)

        return

and in my main script I have something like

logging
import argparse
import logUtils

parser = argparse.ArgumentParser(description="bla bla")
parser.add_argument("-v", dest='v', action='store_true', default=False, help="Verbose mode for debugging")
args = parser.parse_args()

logging.setLoggerClass(logUtils.MyLogger)
logger = logging.getLogger('fancy_name')
if args.v: logger.setLevel(logging.DEBUG)   #this is the line! Here I want to change the level of just the StreamHandler

The last line is the problematic one: it's changing the top logging level!
Suggestions?


Solution

  • Iterate on the logger's handlers to find which is the StreamHandler (assuming you will only have one of those) and changing its level :

    if args.v:
        for handler in logger.handlers:
            if type(handler) == logging.StreamHandler:
                handler.setlevel(logging.DEBUG)
                break