Reputation: 9736
I understand that the root logger has the lastResort
handler that prints to the console if the root logger handler is not configured using logging.basicConfig
and the user makes use of the logging.info/debug/warning/error/critical("some msg")
Or logger = logging.gerLogger()
followed by logger.info/debug/warning/error/critical("some msg")
But for a child logger created using logger = logging.getLogger("someName")
, when we write logger.info/debug/warning/error/critical("some msg")
, and there is no handler configured, and when propagate = true
, then does the child logger have any default handler? Or does it fall back to ancestor's handler, and then to root logger's handler and if ancestors/root logger have no handler then to the root logger lastResort
handler?
If propagate was set to false, then would there be some default handler assigned to child logger?
Upvotes: 4
Views: 1898
Reputation: 430
Short answer: logging.lastResort
Long answer:
According to the doc,if no logging configuration is provided, then:
The event is output using a ‘handler of last resort’, stored in logging.lastResort. This internal handler is not associated with any logger, and acts like a StreamHandler which writes the event description message to the current value of sys.stderr (therefore respecting any redirections which may be in effect). No formatting is done on the message - just the bare event description message is printed. The handler’s level is set to WARNING, so all events at this and greater severities will be output.
Also according to the logging source code:
class Logger(Filterer):
# ...
def callHandlers(self, record):
# ...
# found is the number of handlers
if (found == 0):
if lastResort:
if record.levelno >= lastResort.level:
lastResort.handle(record)
So if there is no handlers, it will call lastResort
, whatever it's a root logger or child logger. lastResort
is actually _StderrHandler(WARNING)
, and this is:
class _StderrHandler(StreamHandler):
"""
This class is like a StreamHandler using sys.stderr, but always uses
whatever sys.stderr is currently set to rather than the value of
sys.stderr at handler construction time.
"""
def __init__(self, level=NOTSET):
"""
Initialize the handler.
"""
Handler.__init__(self, level)
@property
def stream(self):
return sys.stderr
So you can see that it's actually a StreamHandler with WARNING level.
Upvotes: 3