How to implement logging for an imported module?

Joseph L. Casale jcasale at activenetwerx.com
Sun Mar 7 15:14:16 EST 2021


> I couldn't find any information on how to implement logging in a library that
> doesn't know the name of the application that uses it. How is that done?

Hello,
That's not how it works, it is the opposite. You need to know the name of its logger,
and since you imported it, you do.

Logging is hierarchical, organized by dot separated names. However, all loggers
share the same root (top level) logger (a logger without any name, or in other words,
no hierarchical specificity). Loggers are singletons, all loggers share the same root
and each time you get a logger, if any code has previously asked for that logger by
name and therefore created it, you'll get that instance.

When you create a logger, it starts at level WARNING, which means only warnings
or higher are considered.

When you create a handler, it starts at level NOTSET, which means only level 0
and above are considered. Since NOTSET is 0, everything is considered by default.

Loggers pass messages that they are considering to all their handlers, which then
each filter again by the handlers own distinct level.

Don't add handlers in library code (except a null handler).

Do set a level on your library logger that you deem appropriate (INFO is likely
not appropriate).

Then, in your consuming code, if you instantiate a named logger, you won't see
messages that fall below the threshold of the library, and root defaults.

Create (get) a root logger (you don't have to use it) and set the level, and attach a
handler to it. Then get the logger your library uses and set the level to what you want.

Proceed with creating your own named logger and using that in your code, however
when the library emits a log message, it will traverse up, unfiltered and be passed to
a handler.

Think of the process like a tree data structure,  with the single root at the top, and
each immediate child being a named logger without additional specificity (no dot),
and each child of those taking the named plus one dot, followed by another name.

That helps when understanding the design behavior of propagation, and rather than
restate what is already well done, see https://docs.python.org/3/library/logging.html#logging.Logger.propagate. 

It does make a lot of sense, and it facilitates a concise and powerful ability to configure
an application where some messages can be ignored, written to different files, combined
into one, or some even emailed.

Last word of advice, don't fight it by hacking up or patching (somehow?), it will
simply not work right for any other case even slightly different than the one you
somehow beat into submission.

I hope that helps,
Joseph Casale



More information about the Python-list mailing list