Lazy logger message string evaluation
Question: I'm using standard python logging module in my python application:

    
    
    import logging
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger("log")
    while True:
      logger.debug('Stupid log message " + ' '.join([str(i) for i in range(20)]) )
      # Do something
    

The issue is that although debug level is not enable, that stupid log message
is evaluated on each loop iteration, which harms performance badly.

**Is there any solution for this?**

In C++ we have `log4cxx` package that provides macros like this:  
`LOG4CXX_DEBUG(logger, messasage)`  
That effectively evaluates to

    
    
    if (log4cxx::debugEnabled(logger)) {
        log4cxx.log(logger,log4cxx::LOG4CXX_DEBUG, message)
    }
    

But since there are no macros in Python (AFAIK), if there a efficient way to
do logging?


Answer: The logging module already has partial support for what you want to do. Do
this:

    
    
    log.debug("Some message: a=%s b=%s", a, b)
    

... instead of this:

    
    
    log.debug("Some message: a=%s b=%s" % (a, b))
    

The logging module is smart enough to not produce the complete log message
unless the message actually gets logged somewhere.

To apply this feature to your specific request, you could create a lazyjoin
class.

    
    
    class lazyjoin:
        def __init__(self, s, items):
            self.s = s
            self.items = items
        def __str__(self):
            return self.s.join(self.items)
    

Use it like this (note the use of a generator expression, adding to the
laziness):

    
    
    logger.info('Stupid log message %s', lazyjoin(' ', (str(i) for i in range(20))))
    

Here is a demo that shows this works.

    
    
    >>> import logging
    >>> logging.basicConfig(level=logging.INFO)
    >>> logger = logging.getLogger("log")
    >>> class DoNotStr:
    ...     def __str__(self):
    ...         raise AssertionError("the code should not have called this")
    ... 
    >>> logger.info('Message %s', DoNotStr())
    Traceback (most recent call last):
    ...
    AssertionError: the code should not have called this
    >>> logger.debug('Message %s', DoNotStr())
    >>>
    

In the demo, The logger.info() call hit the assertion error, while
logger.debug() did not get that far.

