我正在使用python日志模块(python 3.4.3)。 假设我的日志记录级别设置为INFO,我想使用函数作为我的日志消息的参数。
现在我希望当日志级别降低(例如警告)时,不执行参数函数。
这是真的吗?
示例(控制台):
>>> import math
>>> import logging
>>> logging.basicConfig(level=logging.INFO)
>>> logging.debug('Factorial of 100000=',math.factorial(100000))
>>> */empty output but slightly delayed, small CPU peak/*
>>> logging.debug('Factorial of 10=',math.factorial(10))
>>> */empty output but instant, no noticeable CPU usage/*
该功能可能未执行,但仍有明显的延迟。有人可以解释我可能的原因吗?
答案 0 :(得分:3)
在logging.debug('Factorial of 100000=', math.factorial(100000))
调用之前,您看到传递给logging.debug()
的参数需要 评估 ,并且评估math.factorial(100000)
需要时间
如果最终函数在调用中什么都不做,那么参数仍然会被评估
并不重要从概念上讲,您可以将其视为正在进行
value = math.factorial(100000) # This gets evaluated
logging.debug('Factorial is %d', value) # Even if this is a "no op" call,
# the arg evaluation still takes place
import math
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger()
if logger.getEffectiveLevel() <= logging.DEBUG: # Or use == if you want DEBUG only
logger.debug('Factorial is %d', math.factorial(100000))
使用Python 3&#39; logger.getEffectiveLevel()
鉴于水平按照
排序CRITICAL 50
ERROR 40
WARNING 30
INFO 20
DEBUG 10
NOTSET 0
您可以看到我们的if块(包含<= logging.DEBUG
)只会在DEBUG
及更低版本上运行(因此DEBUG
和NOTSET
)
答案 1 :(得分:1)
问题是你在打电话之前评估了这个功能。解决这个问题的一种方法是使用bakkal描述的logger.getEffectiveLevel()
。但这可能有点冗长。解决此问题的另一种方法是创建一个中间对象,以传递给执行其__str__
函数工作的记录器。这会延迟函数调用,直到日志记录模块确定将发出消息。
例如:
import logging
import math
class CallableMsg:
def __init__(self, func, *args, **kwargs):
self.func = func
self.args = args
self.kwargs = kwargs
def __str__(self):
return str(self.func(*self.args, **self.kwargs))
logging.basicConfig(level=logging.INFO)
# single arg log
logging.info(CallableMsg(math.factorial, 10))
# using the CallableMsg in a format string
logging.info("10! = %s", CallableMsg(math.factorial, 10))
# factorial function never gets evaluated for the debug call
logging.debug(CallableMsg(math.factorial, 1000000))
如果出现错误,日志记录模块也足以保留实际进行日志调用的行。
logging.info(CallableMsg(math.factorial, -1))
输出:
--- Logging error ---
Traceback (most recent call last):
File "C:\Python34\lib\logging\__init__.py", line 971, in emit
msg = self.format(record)
File "C:\Python34\lib\logging\__init__.py", line 821, in format
return fmt.format(record)
File "C:\Python34\lib\logging\__init__.py", line 558, in format
record.message = record.getMessage()
File "C:\Python34\lib\logging\__init__.py", line 319, in getMessage
msg = str(self.msg)
File "C:python\run.py", line 12, in __str__
return str(self.func(*self.args, **self.kwargs))
ValueError: factorial() not defined for negative values
Call stack:
File "<string>", line 1, in <module>
File "C:\Python34\lib\idlelib\run.py", line 126, in main
ret = method(*args, **kwargs)
File "C:\Python34\lib\idlelib\run.py", line 353, in runcode
exec(code, self.locals)
File "C:\python\run.py", line 18, in <module>
logging.info(CallableMsg(math.factorial, -1))
Message: <__main__.CallableMsg object at 0x02ECF970>
Arguments: ()