To create a custom handler with Python’s standard-library logging package, subclass logging.Handler, implement emit(record) to deliver each log record to your destination, then attach the instance to a logger with addHandler(). Use a built-in handler, formatter, or filter instead when that already meets the need.
Example: write formatted records to a custom destination
This template prints the formatted message as a stand-in for a destination-specific operation. Replace print(message) with the operation your handler owns, such as sending data to a service. The example is illustrative; its destination operation is not a production transport.
import logging
class CustomHandler(logging.Handler):
def emit(self, record: logging.LogRecord) -> None:
try:
message = self.format(record)
# Replace this with the destination operation.
print(message)
except Exception:
self.handleError(record)
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
handler = CustomHandler()
handler.setLevel(logging.INFO)
handler.setFormatter(logging.Formatter("%(levelname)s: %(message)s"))
logger.addHandler(handler)
logger.info("Ready")
When logger.info("Ready") is called, the logger passes an eligible record to its handlers. The handler formats it with the formatter configured on that instance, then emit() performs the destination-specific work. The example’s formatter produces a message prefixed with the severity level.
Decide whether you need a custom handler
Subclass Handler when the destination or delivery behavior is genuinely custom. Application code should not instantiate the base Handler directly; the Python Logging HOWTO recommends using a suitable handler class instead. Python Logging HOWTO
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →#1 Best Overall
- Use a built-in handler if it supports the destination. The HOWTO identifies
StreamHandlerandFileHandleras common choices. - Use a formatter to change how records are presented, rather than writing a new destination handler just to change the output layout.
- Use a filter or adapter when you need selection or contextual changes to log records.
- Use a custom handler for destination-specific behavior that existing handlers do not provide.
Set levels, formatting, and filters
Logger and handler levels act at different stages. A logger’s level determines which events it passes onward; a handler’s level determines the minimum severity it will emit. In the example, both are set to INFO, so lower-severity events are filtered before they reach the handler, while the handler also declines records below its own threshold. Add filters when level thresholds alone are not enough to select or modify records.
Set a formatter on the handler with handler.setFormatter(...); self.format(record) in emit() uses that configured formatter. If you attach multiple handlers, configure each one for its own destination and output requirements.
Rank #2
Keep slow destination work off the logging caller
Network requests and email delivery can take time. Synchronous destination work can also block an asynchronous application’s event loop. For performance-sensitive logging, Python’s logging cookbook describes attaching a QueueHandler to enqueue records quickly and using a QueueListener to hand them to destination handlers on another thread. Python Logging Cookbook
Choose queue behavior deliberately: a bounded queue can fill, so decide what the application should do when it does. Moving work to a listener thread does not by itself make multiple processes safe writers to the same file. For multi-process logging, use an explicit coordination or queue/listener design suited to the deployment and verify it against the Python version and process model in use.
Handle failures and release resources
If destination work raises an exception inside emit(), call self.handleError(record) as in the example. Python documents this as the handler error-reporting path; whether the error is visible depends on logging.raiseExceptions. Avoid reporting a handler failure by logging through that same failing handler, which can cause recursive failures. Python logging.Handler reference
logging.shutdown() flushes and closes handlers, and the logging package registers it to run automatically at interpreter exit. If a custom handler owns external resources, define cleanup that fits the handler lifecycle and the destination’s requirements; do not assume interpreter shutdown replaces every application-specific cleanup need. Python logging reference: shutdown
Configure handlers in code or with logging configuration
You can create loggers, handlers, and formatters directly in code, load configuration with fileConfig(), or pass a dictionary to dictConfig(). The logging cookbook also documents using user-defined handlers with dictionary configuration. Choose the approach that fits how the application manages configuration; the custom handler still needs to provide its destination behavior through emit().
Quick Recap
Best Value
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →

