import logging
# root logger
root = logging.getLogger() # root
ch = logging.StreamHandler()
ch.setLevel(logging.WARN)
formatter = logging.Formatter('[root] %(levelname)s - %(message)s')
ch.setFormatter(formatter)
root.addHandler(ch)
# logging as child
c = logging.getLogger('mod')
c.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('[mod] - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
c.addHandler(ch)
c.error('foo')
c.warning('foo')
c.info('foo')
c.debug('foo')
output:
[mod] - ERROR - foo
[root] ERROR - foo
[mod] - WARNING - foo
[root] WARNING - foo
[mod] - INFO - foo
[mod] - DEBUG - foo
It's OK. Level of root is WARN
, so INFO
and DEBUG
of root is not printed.
But when I use basicConfig
:
import logging
# config root logger
logging.basicConfig(level=logging.WARN, format='[root] %(levelname)s - %(message)s')
# logging as child
c = logging.getLogger('mod')
c.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('[mod] - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
c.addHandler(ch)
c.error('foo')
c.warning('foo')
c.info('foo')
c.debug('foo')
output:
[mod] - ERROR - foo
[root] ERROR - foo
[mod] - WARNING - foo
[root] WARNING - foo
[mod] - INFO - foo
[root] INFO - foo
[mod] - DEBUG - foo
[root] DEBUG - foo
The level of basicConfig
is WARN
, why level INFO
and DEBUG
of root can be printed?
And when I use logging.info
, it effects.
You are seeing those
[root]
info and debug messages because your call tologging.basicConfig
creates a root Handler with a level ofNOTSET
. A handler with a level ofNOTSET
will output any message it receives (see Handler.setLevel).This differs from your first example because in your first example you are creating a root handler with a level of
WARN
.The
level=
parameter forlogging.basicConfig
is used to set the level of the root Logger not any root Handler.Log message propagation
Log messages are propagated up to parent Loggers but the level of any parent Loggers is not considered. It is the level of any Handlers that decides what gets "outputted".
From the docs for logging.Logger.propagate:
What is Logger.level for then?
A Logger uses it's level to decide if to propagate a message to its and any parent loggers' handlers.
If a Logger does not have a level set then it asks its ancestor Loggers for their level and uses that (see
logging.Logger.setLevel
).So, the root logger's level is only relevant if you have not set the level on your child logger.