Batu Lab NotesPractical developer guides

Keep library logging quiet with a NullHandler

By Batu ยท English technical notes

Also published in our Blogger archive.

A reusable library can describe events through logging without configuring the application's logging system. logging.NullHandler supports that boundary: it accepts log records and performs no output. This standalone example obtains a named library logger, disables propagation for this isolated demonstration, and attaches one NullHandler with the documented addHandler() method.

The warning uses a fixed message. The assertions confirm that the handler attached by the example is a NullHandler and that its level permits the warning record. The only stdout text comes from print; the warning itself produces no handler output. This demonstrates the handler's no-operation behavior without depending on whether a host application's root logger already has handlers.

A library normally creates its top-level logger at module scope and attaches a null handler there. It should not call basicConfig() merely to suppress output, because that configures application-wide logging. The propagate=False assignment here is specifically for a self-contained example. In a production library, leaving propagation enabled is often useful: an application can configure root once and collect library records through the ordinary logger hierarchy. A null handler also does not choose the library's logging level or make other handlers quiet.

NullHandler has been available since Python 3.1. The official NullHandler documentation describes its no-operation behavior, and Logger.propagate explains ancestor handling.

AI assistance disclosure: This article was drafted with AI assistance and should be adapted to the library's logging contract.

import logging


logger = logging.getLogger("sample.library")
logger.propagate = False
logger.setLevel(logging.DEBUG)
handler = logging.NullHandler()
logger.addHandler(handler)

logger.warning("a library event")

assert isinstance(handler, logging.NullHandler)
assert handler.level <= logging.WARNING
print("library emitted no handler output")
library emitted no handler output