Handlers, Formatters, and Filters
Route log output to files, streams, and custom destinations.
Handlers, Formatters, and Filters is a free Python Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Python Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Handlers Route Log Records
A handler sends log records to a destination: console, file, HTTP endpoint, etc. One logger can have multiple handlers.
import logging
logger = logging.getLogger("myapp")
logger.setLevel(logging.DEBUG)
sh = logging.StreamHandler()
logger.addHandler(sh)
logger.info("Goes to console")StreamHandler
StreamHandler writes to a stream (default sys.stderr). Pass sys.stdout for stdout output.
import logging, sys
logger = logging.getLogger("out")
handler = logging.StreamHandler(sys.stdout)
logger.addHandler(handler)
logger.warning("printed to stdout")FileHandler
FileHandler appends records to a file. Use mode="w" to overwrite on each run.
import logging
logging.basicConfig(
filename="app.log",
filemode="a",
level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s"
)
logging.info("Persisted to disk")RotatingFileHandler
Automatically rotate log files when they exceed a size limit, keeping N backup files.
from logging.handlers import RotatingFileHandler
import logging
handler = RotatingFileHandler(
"app.log", maxBytes=1_000_000, backupCount=5
)
logging.getLogger().addHandler(handler)TimedRotatingFileHandler
Rotate log files on a time schedule — daily, weekly, or by hour — ideal for long-running services.
from logging.handlers import TimedRotatingFileHandler
import logging
handler = TimedRotatingFileHandler(
"app.log", when="midnight", backupCount=7
)
logging.getLogger().addHandler(handler)Formatters
A Formatter controls the text layout of each log record. Attach it to a handler with handler.setFormatter().
import logging
fmt = logging.Formatter(
fmt="%(asctime)s %(levelname)-8s %(name)s — %(message)s",
datefmt="%Y-%m-%dT%H:%M:%S"
)
handler = logging.StreamHandler()
handler.setFormatter(fmt)
logging.getLogger().addHandler(handler)Handler-level Filtering
Each handler has its own level. A record must pass both the logger level and the handler level to be emitted.
import logging
logger = logging.getLogger("app")
logger.setLevel(logging.DEBUG) # logger passes DEBUG+
err_handler = logging.FileHandler("errors.log")
err_handler.setLevel(logging.ERROR) # only ERROR+
logger.addHandler(err_handler)Custom Filters
Subclass logging.Filter and override filter(record) to accept or reject records by any criterion.
import logging
class SensitiveFilter(logging.Filter):
def filter(self, record):
return "password" not in record.getMessage().lower()
handler = logging.StreamHandler()
handler.addFilter(SensitiveFilter())
logging.getLogger().addHandler(handler)Adding Extra Fields with a Filter
Filters can also mutate the record to inject additional fields (e.g., request ID) before formatting.
import logging
class RequestIDFilter(logging.Filter):
def __init__(self, request_id):
self.request_id = request_id
def filter(self, record):
record.request_id = self.request_id
return True
# fmt: "%(request_id)s %(message)s"Multiple Handlers on One Logger
Add several handlers to send the same log records to multiple destinations simultaneously.
import logging
logger = logging.getLogger("multi")
logger.addHandler(logging.StreamHandler()) # console
logger.addHandler(logging.FileHandler("audit.log")) # file
logger.setLevel(logging.INFO)
logger.info("Both destinations receive this")Disabling Propagation
Set logger.propagate = False to stop records from bubbling up to the root logger and being double-logged.
import logging
logger = logging.getLogger("mylib")
logger.propagate = False # stays here, does not reach root
logger.addHandler(logging.StreamHandler())Quick Check
What method attaches a Formatter to a Handler?
Recap
Handlers route records; formatters style them; filters selectively pass or block them. Use RotatingFileHandler for size-limited logs and TimedRotatingFileHandler for date-based rotation.
Frequently asked questions
Is the “Handlers, Formatters, and Filters” lesson free?
Yes — the full text of “Handlers, Formatters, and Filters” is free to read here on the web, and the Python Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Python Academy course, upgrade to CoddyKit PRO.
What will I learn in “Handlers, Formatters, and Filters”?
Route log output to files, streams, and custom destinations. You practise Python Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Python Academy?
No prior experience is required. Python Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Handlers, Formatters, and Filters” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Python Academy lesson?
Yes. Every Python Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- The logging Module Basics
- Handlers, Formatters, and Filters
- Structured Logging
- Debugging with pdb