import logging
root_logger = logging.getLogger()
root_handler = logging.StreamHandler()
root_handler.setFormatter(logging.Formatter('ROOT: %(message)s'))
root_logger.addHandler(root_handler)
# 父Logger配置
parent_logger = logging.getLogger('parent')
parent_handler = logging.StreamHandler()
parent_handler.setFormatter(logging.Formatter('PARENT: %(message)s'))
parent_logger.addHandler(parent_handler)
parent_logger.setLevel(logging.ERROR)
# 子Logger(默认propagate=True)
child_logger = logging.getLogger('parent.child')
child_handler = logging.StreamHandler()
child_handler.setFormatter(logging.Formatter('CHILD: %(message)s'))
child_logger.addHandler(child_handler)
child_logger.setLevel(logging.INFO)
child_logger.info("INFO msg")
Running Result:
/Users/egonever/DjangoByExamples/mysite/logging_demystified/example3.py
CHILD: INFO msg
PARENT: INFO msg
ROOT: INFO msg
Process finished with exit code 0
Why "INFO msg" was logged three times?
The message "INFO msg" is logged three times due to Python's logging hierarchy and the default propagation behavior (propagate=True). Here's the detailed explanation:
-
Child Logger Handling
Thechild_loggerfirst processes the message through its own handler (child_handler), which outputs:
CHILD: INFO msg
This occurs because the message level (INFO) meets the child logger's level (INFO). -
Propagation to Parent Logger
Sincepropagate=True(default), the message is passed to the parent logger (parent_logger). Despite the parent's level beingERROR, the message is still processed by the parent's handler (parent_handler), resulting in:
PARENT: INFO msg
Note: The parent logger's level only filters messages before they reach its handlers, but propagation bypasses this check. -
Propagation to Root Logger
The message further propagates to the root logger, which has no level set (defaults toWARNING). However, the root logger's handler (root_handler) still processes the message, producing:
ROOT: INFO msg
Similar to the parent logger, the root's level doesn't block propagated messages.
Key Points
- Propagation allows messages to bubble up the logger hierarchy (
child → parent → root). - Handler levels are independent of logger levels.
- When a handler is created, the level is set to
NOTSETwith numeric value 0(which causes all messages to be processed). - To avoid duplicate logs, either:
- Set
child_logger.propagate = False, or - Configure logger levels and handlers more carefully.
- Explicitly configure handlers' level by using setLevel method.
- Set
4723

被折叠的 条评论
为什么被折叠?



