Levels checking (filtering) in logging module
In Python's logging
module, both logger levels and handler levels control which log messages are processed, but they operate at different stages of the logging workflow. Here's a clear comparison:
1. Logger Level
1.1 What it does:
Acts as the first filter. Determines whether a log message enters the logging system.
1.2 How to set:
logger.setLevel(logging.INFO) # Logger level set to INFO
1.3 Behavior:
- If the message's severity is below the logger level, it is ignored immediately.
- If it meets/exceeds the logger level, the message is passed to attached handlers.
- Default level:
WARNING
(if not explicitly set).
1.4 Example:
logger.setLevel(logging.INFO)
logger.debug("Debug message") # Ignored (below INFO)
logger.info("Info message") # Passed to handlers
2. Handler Level
2.1 What it does:
Acts as the second filter. Determines whether a message (that passed the logger level) is output by a specific handler.
2.2 How to set:
handler.setLevel(logging.ERROR) # Handler level set to ERROR logger.addHandler(handler)
2.3 Behavior:
- Only messages meeting/exceeding the handler's level are processed by that handler.
- Different handlers can have different levels (e.g., log errors to a file but warnings to the console).
- Default level:
NOTSET.
2.4 Example:
# Handler 1: Logs WARNING+ to console
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.WARNING) # Handler level
# Handler 2: Logs ERROR+ to file
file_handler = logging.FileHandler("errors.log") file_handler.setLevel(logging.ERROR) # Handler level logger.addHandler(console_handler)
logger.addHandler(file_handler)
# Test messages
logger.warning("Warning!") # Output to console only
logger.error("Error!") # Output to console AND file
3. Key Interaction
A message must pass BOTH levels to be output by a handler
Logger Level (Gate 1) Handler Level (Gate 2)
Message ----------------------> ----------------------> Output (e.g., INFO, WARNING) (e.g., ERROR, CRITICAL)
4. Critical Rules
4.1 Summary Table
Scenario | Outcome |
---|---|
Message level < Logger level | Message ignored entirely. |
Message level < Handler level | Message reaches handler but is discarded by that handler. |
Message level ≥ Both levels | Message is processed by the handler (e.g., printed, saved, etc.). |
4.2 Example Workflow
import logging
logger = logging.getLogger("example")
logger.setLevel(logging.WARNING) # Logger level: WARNING
# Handler 1: Level WARNING (logs to console)
console = logging.StreamHandler()
console.setLevel(logging.WARNING) # Handler level: WARNING logger.addHandler(console)
# Handler 2: Level ERROR (logs to file)
file = logging.FileHandler("errors.log")
file.setLevel(logging.ERROR) # Handler level: ERROR
logger.addHandler(file)
# Test
logger.info("Info") # Blocked by logger (level < WARNING)
logger.warning("Alert!") # Passed by logger → printed by console (level ≥ WARNING),ignored by file (level < ERROR)
logger.error("FAIL!") # Passed by logger → printed by console AND written to file (level ≥ both)
4.3 Key Takeaways
- Logger level is the global gatekeeper.
- Handler levels fine-tune where messages go (e.g., console vs. file).
- Set logger level to the lowest severity you want to process.
- Set handler levels to selectively output messages per destination.
Use this to control verbosity efficiently (e.g., log debug messages to a file while showing only errors in the console).