Package: well-behaved-logging
Well-Bahaved Logging (wblog)1. OverviewPython standardloggingpackage has great functionalities, however,
it is bit confusing.For small one-time script, it is fine to use root logger functions
(e.g.logging.debug()) with global configlogging.basicConfig().
Moreover you don't need to calllogging.basicConfig()explicitly
becauselogging.debug()etc. internally call it
to ensure the root logger has a handler.For importable library, the situation is completely different. It is
officially recommended that loggers should not have any handlers
exceptlogging.NullHandler. Additionally, in our opinion, logging
should be configurable by end users through top level main script or
application.Here, we provide a set of small utility functions to help library
developpers realize well-behaved logging.2. Installwblog doesn't have any dependencies.pipinstallwell-behaved-logging3. Usage3.1 Get and Use Logger at ModuleYou can get module-level preparedlogging.Loggerinstance bywblog.getLogger()function. The function automatically detects the
module name (aka.__name__), so that you don't need to pass it.The returned logger is standardlogging.Logger, so that you can call
logging methods (e.g.Logger.debug()) as usual.importwbloglogger=wblog.getLogger()# No __name__ is neededlogger.debug("Debug message")Since the logger is standartlogging.Logger, it is also possible to
set log level and to add handlers manually, however, it is not
recommended.3.2 Start Logging (by End Users or Application)wblog.start_logging(name, level=None, *, handlers=None, propagate=False)function enables logging of a specified package or module
(as long as they are well behaved).If no handlers are passed,logging.StreamHandleris used and log
messages are printed out at consolesys.stderr.Ifpropagate=Flase(default), the module stops delegation to parent
logger.We assume the module logger doesn't have any handlers exceptlogging.NullLogger,
and the function doesn't remove handlers.3.3 Stop Logging (by End Users or Application)wblog.stop_logging(name)function disables logging of a specified
package or module. It removes its log level and all handlers fromname,
and enables delegation to the parent logger again.3.4 Advanced Usagewblog doesn't manage handlers and fomatters.
End users or application need to prepare them.Handler defines how and where the logging messages are outputted.
There are many handlers are implemented at theloggingpackages
(ref1,ref2).StreamHandlerwrites logs to stream (e.g. srandard error).FileHandlerwrites logs to a file.RotatingFileHandlerwrites logs to a file with log rotation.etc.logging.Handlerclass can set log level and filter, so that it is
also possible that all logs are shown on the console standard error
and only logs overlogging.WARNINGare written on the log file.If you set only a single handler to your logger, we recommend not to
specify log level at the handler, then the handler manages all logs
from the logger.Formatter defines logging format
(ref)
and is set to handlers.The default format is%(levelname)s:%(name)s:%(message)swhich
doesn't include date time information at all.Information can be used are describedhere.4. Designroot logger <-- package top-level logger <-- ... <-- module loggerWe setlogging.NullHandlerto the package top-level logger.When users change root logger config bylogging.basicConfig(),
other (unconfigured) loggers should follow.If users want to enable only a certain package or module, we should
set log level and handlers to that level logger. Generally, delegation
to its parent logger can be stopped, but it is better if it is
configurable.Disabling such logging reverts to the original log level
(logging.NOTSET), removes all handlers, and enables delegation again.5. Other Logging LibrariesThere are many logging libraries. As far as we know, they are designed
for end users to log easily.logzeroEasy to setupLogger,Handler, andFormatterBuilt on the standardloggingpackageFor end users or application, not for libraryLoguruEasy to loggingBuilt from scratchFor end users or application, not for library