-
-
Save schnittstabil/9372911 to your computer and use it in GitHub Desktop.
| import logging | |
| logging.basicConfig(level=logging.INFO) | |
| logger = logging.getLogger("log") | |
| def simple(): | |
| if logger.isEnabledFor(logging.DEBUG): | |
| logger.debug( | |
| 'Stupid log message ' + ' '.join([str(i) for i in range(20)]) | |
| ) | |
| # Do something | |
| class lazyjoin: | |
| def __init__(self, s, items): | |
| self.s = s | |
| self.items = items | |
| def __str__(self): | |
| return self.s.join(self.items) | |
| def lazy(): | |
| logger.debug( | |
| 'Stupid log message %s', lazyjoin(' ', (str(i) for i in range(20))) | |
| ) | |
| # Do something | |
| if __name__ == '__main__': | |
| import timeit | |
| print(min(timeit.repeat("simple()", setup="from __main__ import simple"))) | |
| print(min(timeit.repeat("lazy()", setup="from __main__ import lazy"))) |
for the record, doing the following resulted in almost the same result for both methods. It does describe a real scenario in my case, in which the lazy logging method doesn't need any parameters and simply takes stuff from self to generate the debug message (you can see what I ended up doing here)
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("log")
def simple():
if logger.isEnabledFor(logging.DEBUG):
logger.debug(
'Stupid log message ' + ' '.join([str(i) for i in range(20)])
)
# Do something
class lazyjoin:
def __init__(self, s, items):
self.s = s
self.items = items
def __str__(self):
return self.s.join(self.items)
def lazy(lazy_log):
logger.debug(
'Stupid log message %s', lazy_log
)
# Do something
if __name__ == '__main__':
import timeit
print(min(timeit.repeat("simple()", setup="from __main__ import simple")))
print(min(timeit.repeat("lazy(lazy_log)", setup="from __main__ import lazy, lazyjoin; lazy_log = lazyjoin(' ', (str(i) for i in range(20)))")))EDIT: syntax highligting added by @schnittstabil
@guyarad You're ignoring the time needed to create the lazyjoin instance lazy_log:
setup="… lazy_log = lazyjoin(' ', (str(i) for i in range(20)))"For a real world scenario you have to measure that time too.
At the time of writing my stackoverflow answer, logger.isEnabledFor(logging.DEBUG) was 4 times faster than creating a lazyjoin instance.
See also my stackoverflow answer to Python: how to do lazy debug logging.
Nevertheless, even in your scenario, I see no need to create those expensive LazyLogging instances.
Instead you could use a simple and efficient lazy_debug function:
def lazy_debug(logger, msg, fn):
if logger.isEnabledFor(logging.DEBUG):
logger.debug(msg, fn())
class MyClass(object):
def __init__(self):
pass
def _debug_1(self):
return "my debugging string 1"
def _debug_2(self):
return "my debugging string 2"
def _debug_3(self):
return "my debugging string 3"
def m_1(self):
lazy_debug(logger, "Info: %s", self._debug_1)
def m_2(self):
lazy_debug(logger, "Info: %s", self._debug_2)
def m_3(self):
lazy_debug(logger, "Info: %s", self._debug_3)If you want to improve this, you may extend the logger class with a lazy_debug method, which is hard though, IIRC.
my result: