2

Suppose i have a statement like this

logging.debug('%r', do_really_expensive_computation())
or
logging.debug('%r', find_my_object().do_really_expensive_computation())

When logging level is set above DEBUG it will not log, but it will still evaluate the arguments before calling logging.debug() and execute do_really_expensive_computation() also find_my_object() could be quite heavy.

Is there any good pattern to skip all computation involved in logging when below current level?

anverx
  • 107
  • 1
  • 7
  • 2
    `if logger.isEnabledFor(logging.DEBUG): do_expensive()`. For more details checkout the official python documentation https://docs.python.org/3.1/library/logging.html#optimization – Elbehery Feb 05 '20 at 09:14
  • Thanks, that could be the least painful way of doing it. – anverx Feb 05 '20 at 10:38
  • Looks like this have been asked before several times, just with different wording. https://stackoverflow.com/questions/21377020/python-how-to-do-lazy-debug-logging https://stackoverflow.com/questions/35411265/python-logger-debug-converting-arguments-to-string-without-logging – anverx Feb 06 '20 at 07:12

1 Answers1

4

One approach is to create a helper class with a __repr__ method that returns the value of a given callback function, and pass to the logger an instance of the helper class initialized with the expensive function object for a lazy evaluation:

class r:
    def __init__(self, callback):
        self.callback = callback

    def __repr__(self):
        return repr(self.callback())

so that:

import logging

def expensive():
    print('this is expensive')
    return 1

print('debug:')
logging.debug('%r', r(expensive))
print('error:')
logging.error('%r', r(expensive))

outputs:

debug:
error:
this is expensive
ERROR:root:1
blhsing
  • 91,368
  • 6
  • 71
  • 106