Nov-03-2018, 02:29 PM
(This post was last modified: Nov-04-2018, 05:57 AM by Gribouillis.)
Simply use
BraceLogger.getLogger()
instead of logging.getLogger()
as shown in the code below. This tip is derived from a paragraph in the logging cookbook.import logging __version__ = "2018.11.03" class BraceMessage(object): #see: https://docs.python.org/3/howto/logging-cookbook.html#using-custom-message-objects def __init__(self, msg, *args, **kwargs): self.msg = msg self.args = args self.kwargs = kwargs def __str__(self): try: return self.msg.format(*self.args, **self.kwargs) except Exception as exc: return "Interpolation error during message formatting\n .format({}, *{}, **{})\n{}: {}".format( repr(self.msg), self.args, self.kwargs, type(exc).__name__, str(exc)) class BraceLogger(logging.getLoggerClass()): _reserved = (('exc_info', None), ('extra', None), ('stack_info', False)) def _log(self, level, msg, args, **kwargs): d = {k: kwargs.pop(k, v) for k, v in self._reserved} return super()._log( level, BraceMessage(msg, *args, **kwargs), (), **d) def __init__(self, *args, **kwargs): raise TypeError('BraceLogger class cannot be directly instantiated') @classmethod def getLogger(cls, name): logger = logging.getLogger(name) # this is frowned upon, but it is so convenient here! logger.__class__ = cls return logger if __name__ == '__main__': logging.basicConfig() log = BraceLogger.getLogger(__name__) log.setLevel(logging.DEBUG) log.info('{} Todays wisdom is that {x} + {y} = {z}', 'Hello!', x=1, z=3, y=2) try: 1./0. except Exception: log.exception('Something {} happened!', 'BAD') log.warning("This is the END...")
Output:INFO:__main__:Hello! Todays wisdom is that 1 + 2 = 3
ERROR:__main__:Something BAD happened!
Traceback (most recent call last):
File "bracelogger.py", line 42, in <module>
1./0.
ZeroDivisionError: float division by zero
WARNING:__main__:This is the END...
Note: this code is not very clean because we assign to the __class__
member instead of trying to properly create a subclass instance. On the other hand, this minimizes the interference with the logging module's internals.