Search code examples
pythonloggingpython-logging

About NOTSET in python logging


As the logger.setLevel doc says:

When a logger is created, the level is set to NOTSET (which causes all messages to be processed when the logger is the root logger, or delegation to the parent when the logger is a non-root logger). Note that the root logger is created with level WARNING.

so I think if I create a root logger, with level NOTSET, the debug and info log will display.

The code use basicConfig to set root logger's level to NOTSET is right:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import logging

logging.basicConfig(level=logging.NOTSET)
log = logging.getLogger()

log.debug('debug')
log.info('info')
log.warning('warning')
log.error('error')
log.critical('critical')

and output is:

DEBUG:root:debug
INFO:root:info
WARNING:root:warning
ERROR:root:error
CRITICAL:root:critical

But if I create a root logger, and add handler with NOTSET level to it, such as:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import logging

log = logging.getLogger()
hd = logging.StreamHandler()
hd.setLevel(logging.NOTSET)
log.addHandler(hd)

log.debug('debug')
log.info('info')
log.warning('warning')
log.error('error')
log.critical('critical')

the output is:

warning
error
critical

but I think it will also output the debug and info message.


Solution

  • OK, I misunderstand the Logger's level and Handler's Level, in the doc:

    The setLevel() method, just as in logger objects, specifies the lowest severity that will be dispatched to the appropriate destination. Why are there two setLevel() methods? The level set in the logger determines which severity of messages it will pass to its handlers. The level set in each handler determines which messages that handler will send on.

    If I change code to this, will be ok:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    import logging
    
    log = logging.getLogger()
    log.setLevel(logging.NOTSET) # Set Logger's level to NOTSET, default is WARNING
    #print "Logger's Level: ", log.level
    hd = logging.StreamHandler()
    hd.setLevel(logging.NOTSET)
    #print "Handler's Level: ", hd.level
    log.addHandler(hd)
    
    log.debug('debug')
    log.info('info')
    log.warning('warning')
    log.error('error')
    log.critical('critical')