PEP8 compliant way to switch log for the whole package
I have a package with this structure:
mypackage
|
+---- a.py
+---- b.py
+---- __init__.py
this package is sometimes used as a library, sometimes interactively with IPython, so I need to set up the logging differently in both cases:
- interactive: print logs to console, so loggers must have a handler
StreamHandler
- library: let the user customize the logging, so the loggers must have a handler
NullHandler
In __init__.py
I do this:
import logging
import a
import b
logging.getLogger(__name__).addHandler(logging.NullHandler())
def get_loggers():
"""
Get all the logger objects instantiated for the current package
"""
loggers = []
for logger in logging.Logger.manager.loggerDict.values():
if not isinstance(logger, logging.Logger):
continue
if logger.name.startswith(__name__):
loggers.append(logger)
return loggers
def enable_logs():
"""
Configure loggers to print on stdout/stderr
"""
handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter(
'%(name)s :: %(levelname)s :: %(message)s'))
for logger in get_loggers():
logger.removeHandler(handler)
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
logger.propagate = False
def disable_logs():
"""
Configure loggers not to print anywhere
"""
handler = logging.NullHandler()
for logger in get_loggers():
logger.removeHandler(handler)
logger.addHandler(handler)
logger.propagate = False
a.py
and b.py
start with:
import logging
log = logging.getLogger(__name__)
log.addHandler(logging.NullHandler())
So now I can enable / disable logging by doing the following:
import mypackage
mypackage.enable_logs()
mypackage.disable_logs()
But this solution does not match PEP8
, because in __init__.py
I import modules that are not used. Note that they don't need to import them, but I want to because then their respective registrars are created when the package is imported.
Question1: Is their PEP8 compliant way to achieve the same goal?
Question2: Is it subjective, maybe PEP8 in this case?
source to share
You can call this function at the beginning of your logs enable and disable functions to dynamically load modules, but I think the PEP traversal in this way might change:
import glob
import imp
import os
def load_modules(module_names=None):
if module_names is None:
cur_dir = os.path.realpath(os.path.dirname(__file__))
module_wc = '{}/*.py'.format(cur_dir)
module_names = [mn for mn in glob.glob(module_wc) if not mn.startswith('_')]
modules = map(imp.load_source, module_names)
return modules
source to share