[loggingTools] add Logger class with support for 'lastResort' stderr handler

Both _StderrHandler and Logger.callHandlers included here are taken from Python 3.5's
logging.py source.

I only set logging.lastResort if it's not already set (i.e. for Python < 3.2).
This commit is contained in:
Cosimo Lupo 2016-01-29 18:36:21 +00:00
parent 141cc7b6c2
commit f3116ad4d0

View File

@ -87,6 +87,58 @@ class LevelFormatter(logging.Formatter):
return super(LevelFormatter, self).format(record)
class _StderrHandler(logging.StreamHandler):
""" This class is like a StreamHandler using sys.stderr, but always uses
whatever sys.stderr is currently set to rather than the value of
sys.stderr at handler construction time.
"""
def __init__(self, level=logging.NOTSET):
"""
Initialize the handler.
"""
logging.Handler.__init__(self, level)
@property
def stream(self):
return sys.stderr
if not hasattr(logging, 'lastResort'):
# for Python pre-3.2, set a "last resort" handler used when clients don't
# explicitly configure logging
logging.lastResort = _StderrHandler(logging.WARNING)
class Logger(logging.Logger):
""" Add support for 'lastResort' handler introduced in Python 3.2.
You can set logging.lastResort to None, if you wish to obtain the pre-3.2
behaviour. Also see:
https://docs.python.org/3.5/howto/logging.html#what-happens-if-no-configuration-is-provided
"""
def callHandlers(self, record):
# this is the same as Python 3.5's logging.Logger.callHandlers
c = self
found = 0
while c:
for hdlr in c.handlers:
found = found + 1
if record.levelno >= hdlr.level:
hdlr.handle(record)
if not c.propagate:
c = None # break out
else:
c = c.parent
if (found == 0):
if logging.lastResort:
if record.levelno >= logging.lastResort.level:
logging.lastResort.handle(record)
elif logging.raiseExceptions and not self.manager.emittedNoHandlerWarning:
sys.stderr.write("No handlers could be found for logger"
" \"%s\"\n" % self.name)
self.manager.emittedNoHandlerWarning = True
def configLogger(**kwargs):
""" Do basic configuration for the logging system. This is more or less
the same as logging.basicConfig with some additional options and defaults.