Victor Parmar
Victor Parmar

Reputation: 5789

Python setLevel on StreamHandler does not work

I have setup logging as follows:

def setUp():

    LOG_FORMAT = '%(asctime)s %(levelname)-8s %(name)s %(message)s'
    #LOG_FORMAT = '%(asctime)s %(name)s %(message)s'

    logging.basicConfig(level=logging.DEBUG, format=LOG_FORMAT)
    formatter = logging.Formatter(LOG_FORMAT)

    ch = logging.StreamHandler()
    ch.setLevel(logging.ERROR)
    ch.setFormatter(formatter)
    logging.getLogger().addHandler(ch)

    LOG_FILENAME = 'file.log'
    fh = logging.FileHandler(LOG_FILENAME, 'w')
    fh.setLevel(logging.DEBUG)
    fh.setFormatter(formatter)
    logging.getLogger().addHandler(fh)

However, the console still shows DEBUG messages. Am I missing something here?

Note that setting the level to ERROR on fh works fine.

Upvotes: 4

Views: 3810

Answers (2)

Piotr Dobrogost
Piotr Dobrogost

Reputation: 42455

From Python docs on logging.basicConfig:

Does basic configuration for the logging system by creating a StreamHandler with a default Formatter and adding it to the root logger.

As you set debug level of root logger to logging.DEBUG and you didn't switched off forwarding messages up to the root logger your DEBUG messages get logged by this StreamHandler created by basicConfig

Upvotes: 2

jcollado
jcollado

Reputation: 40414

I think you need to remove the call to logging.basicConfig. That function adds another logging.StreamHandler that probably is the one that is printing the messages you don't want to be printed.

To check this you can take a look at the handlers attribute for the root logger (it's a list with all the handlers being used) and verify how many logging.StreamHandlers there are. Also, probably the message with level set to logging.ERROR are printed twice because of the two logging.StreamHandlers.

My final advice is avoid using logging.basicConfig if you're going to explicitly configure the handlers in the code.

Edit: Just for completeness, the source code of logging.BasicConfig is as follows:

if len(root.handlers) == 0:
    filename = kwargs.get("filename")
    if filename:
        mode = kwargs.get("filemode", 'a')
        hdlr = FileHandler(filename, mode)
    else:
        stream = kwargs.get("stream")
        hdlr = StreamHandler(stream)
    fs = kwargs.get("format", BASIC_FORMAT)
    dfs = kwargs.get("datefmt", None)
    fmt = Formatter(fs, dfs)
    hdlr.setFormatter(fmt)
    root.addHandler(hdlr)
    level = kwargs.get("level")
    if level is not None:
        root.setLevel(level)

where you can see that unless filename is passed, a logging.StreamHandler is created.

Upvotes: 2

Related Questions