Not*_* ID 7 python logging lazy-evaluation
我有一些像这样的python:
def foo():
logger = logging.getLogger()
# do something here
logger.debug('blah blah {}'.format(expensive_func()))
foo()
Run Code Online (Sandbox Code Playgroud)
where expensive_func()是一个返回字符串的函数,执行起来很昂贵.
在开发时,日志级别设置为DEBUG,并且expensive_func()执行,消息被记录,一切都很好.
问题是,当我将日志级别设置为严格大于DEBUG(例如WARNING)时,在生产环境中,显然返回值expensive_func()不会被记录,但昂贵的函数本身仍将被执行.
我的问题是:当日志记录级别为WARNING时,如何防止python出现昂贵的函数?
我不想删除该调试行或添加像if level > DEBUG: return昂贵的功能.
谢谢.
编辑
我刚刚访问了懒惰记录器消息字符串评估,但不满意,主要是因为:
class Lazy:
def __init__(self, func, *a, **ka):
self.func= func
self.a = a
self.ka= ka
def __str__(self):
return str(self.func(*self.a, **self.ka))
# Though this is ugly, it works
logger.debug('Message: %s', Lazy(expensive_func))
# What if I wanted to do this?
# logger.debug('Message: {}'.format(expf_1(expf_2(some_arg))))
# Maybe I can modify class Lazy to make something like this to work
# but it really doesn't feel right
# logger.debug('Message: {}', Lazy(expf_1, Lazy(expf_2, some_arg)))
Run Code Online (Sandbox Code Playgroud)
看看这部分文档.
更新:日志记录已经支持延迟评估,但与您的comnment中描述的方式略有不同.例如,请参阅以下脚本:
import logging
def expensive_func(*args):
print('Expensive func called: %s' % (args,))
return sum(args)
class DeferredMessage(object):
def __init__(self, func, *args):
self.func = func
self.args = args
def __str__(self):
return 'Message {0}'.format(self.func(*self.args))
if __name__ == '__main__':
logging.basicConfig()
logging.info(DeferredMessage(expensive_func, 1, 2))
logging.warning(DeferredMessage(expensive_func, 3, 4))
logging.error(DeferredMessage(expensive_func, 5, 6))
Run Code Online (Sandbox Code Playgroud)
运行上面的脚本时,应该打印
Expensive func called: (3, 4)
WARNING:root:Message 7
Expensive func called: (5, 6)
ERROR:root:Message 11
Run Code Online (Sandbox Code Playgroud)
这表明只在必要时调用潜在的昂贵功能.当然,上面的示例可以推广到允许将格式字符串传递给DeferredMessage,以及使用kwargs等等.
正如Vinay Sajip建议的那样,您可以执行以下操作:
def foo():
logger = logging.getLogger()
if logger.isEnabledFor(logging.DEBUG):
logger.debug('blah blah {}'.format(expensive_func()))
logger.debug('Message: {}'.format(expf_1(expf_2(some_arg))))
logger.debug('Message: {}', Lazy(expf_1, Lazy(expf_2, some_arg)))
foo()
Run Code Online (Sandbox Code Playgroud)
哪个已经懒了!
那是因为那时的表达式
logger.debug('blah blah {}'.format(expensive_func()))
logger.debug('Message: {}'.format(expf_1(expf_2(some_arg))))
logger.debug('Message: {}', Lazy(expf_1, Lazy(expf_2, some_arg)))
Run Code Online (Sandbox Code Playgroud)
仅当且仅当logger.isEnabledFor(logging.DEBUG)返回时才进行评估True,即当且仅当需要进行评估时.
更
logging.info(DeferredMessage(expensive_func, 1, 2))
Run Code Online (Sandbox Code Playgroud)
并不像人们想象的那样懒惰:DeferredMessage(expensive_func, 1, 2)必须以热切的方式进行评估.这比评估更慢:
if logger.isEnabledFor(logging.DEBUG):
Run Code Online (Sandbox Code Playgroud)