logging is a tree¶
Level: 201 → 301 · for Python programmers
Stub — an outline, not a lesson. There is no runnable example behind this page yet, so nothing on it has been through the check that backs every other claim in this library. The bullets below are the questions the finished page has to answer.
One line: Loggers are nodes in a tree named by dots, and a record travels from the logger it was made on up to the root and out through every handler on the way — so basicConfig() configures the root once and does nothing the second time, a handler added to both app and app.db prints each line twice, and a library that never configured anything still gets its warnings printed by the root's last-resort handler.
What the finished page has to answer¶
getLogger('app.db').parent is getLogger('app'), propagation, and the difference between a logger's level and a handler's level, measured with handlers that write toio.StringIOso the key holds the text.basicConfig()as a no-op once the root has a handler,force=True, and the trap of a module-levellogging.warning()call configuring the root behind your back.- The double line: one handler on the parent and one on the child, and
propagate = False. lastResort: aWARNINGfrom an unconfigured program still reaches stderr, and anINFOdoes not.NullHandlerfor a library,getLogger(__name__)for the tree to follow the packages, and%(name)sin the format to see it.log.info('%s', x)againstlog.info(f'{x}'): the first formats only if the record is emitted.logging.exception()inside anexceptblock, and what it adds thaterror()does not, which is The traceback is on the object.
See also¶
- Standard in, standard out, and pipes: where stderr goes
logging↗ in the library reference and the logging HOWTO ↗- The Rust library's observability chapter ↗, where the tree is a
tracingsubscriber