As a side note, you don't have to take a performance hit to use new style formatting with logging. You can pass any object to logging.debug
, logging.info
, etc. that implements the __str__
magic method. When the logging module has decided that it must emit your message object (whatever it is), it calls str(message_object)
before doing so. So you could do something like this:
import logging
class NewStyleLogMessage(object):
def __init__(self, message, *args, **kwargs):
self.message = message
self.args = args
self.kwargs = kwargs
def __str__(self):
args = (i() if callable(i) else i for i in self.args)
kwargs = dict((k, v() if callable(v) else v) for k, v in self.kwargs.items())
return self.message.format(*args, **kwargs)
N = NewStyleLogMessage
# Neither one of these messages are formatted (or calculated) until they're
# needed
# Emits "Lazily formatted log entry: 123 foo" in log
logging.debug(N('Lazily formatted log entry: {0} {keyword}', 123, keyword='foo'))
def expensive_func():
# Do something that takes a long time...
return 'foo'
# Emits "Expensive log entry: foo" in log
logging.debug(N('Expensive log entry: {keyword}', keyword=expensive_func))
This is all described in the Python 3 documentation (https://docs.python.org/3/howto/logging-cookbook.html#formatting-styles). However, it will work with Python 2.6 as well (https://docs.python.org/2.6/library/logging.html#using-arbitrary-objects-as-messages).
One of the advantages of using this technique, other than the fact that it's formatting-style agnostic, is that it allows for lazy values e.g. the function expensive_func
above. This provides a more elegant alternative to the advice being given in the Python docs here: https://docs.python.org/2.6/library/logging.html#optimization.