[英]Python Logging overhead with function in argument
I am using python logging module (python 3.4.3). 我正在使用python日志模块(python 3.4.3)。 Let's say my logging level is set to INFO and I would like to use a function as an argument of my logging message. 假设我的日志记录级别设置为INFO,我想使用函数作为我的日志消息的参数。
Now I would expect when log level is decreased (eg WARNING) that the argument functions are not executed. 现在我希望当日志级别降低(例如警告)时,不执行参数函数。
Is this true? 这是真的?
Example (console): 示例(控制台):
>>> 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/*
The function is probably not executed, but still there is noticable delay. 该功能可能未执行,但仍有明显的延迟。 Could someone explain me please the possible cause? 有人可以解释我可能的原因吗?
Well you see the arguments you pass to logging.debug('Factorial of 100000=', math.factorial(100000))
need to be evaluated before logging.debug()
gets called , and evaluating math.factorial(100000)
takes time 那么你看到传递给logging.debug('Factorial of 100000=', math.factorial(100000))
的参数logging.debug('Factorial of 100000=', math.factorial(100000))
需要在调用 logging.debug()
之前进行评估 ,并且评估math.factorial(100000)
需要时间
It doesn't matter if ultimately the function does nothing in its call, the arguments will still get evaluated 如果函数最终在调用中没有做任何事情都没关系,那么参数仍然会得到评估
Conceptually you can think of it as doing 从概念上讲,你可以把它想象成一样
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))
Using Python 3's logger.getEffectiveLevel() 使用Python 3的logger.getEffectiveLevel()
Given that the levels are ordered as 鉴于水平被命令为
CRITICAL 50
ERROR 40
WARNING 30
INFO 20
DEBUG 10
NOTSET 0
You can see that our if block (with <= logging.DEBUG
) will only run on DEBUG
and below (so DEBUG
and NOTSET
) 你可以看到我们的if块(带<= logging.DEBUG
)只能在DEBUG
及以下运行(所以DEBUG
和NOTSET
)
The problem is that you evaluate the function before you call. 问题是你在打电话之前评估这个功能。 One way of dealing with this is using logger.getEffectiveLevel()
as described by bakkal. 解决这个问题的一种方法是使用logger.getEffectiveLevel()
描述的logger.getEffectiveLevel logger.getEffectiveLevel()
。 This can be a bit verbose though. 但这可能有点冗长。 Another way to get around this is to create an intermediary object to pass to the logger that does the work in it's __str__
function. 解决此问题的另一种方法是创建一个中间对象,以传递给在其__str__
函数中执行工作的记录器。 This delays the function call until the logging module is sure the message will be emitted. 这会延迟函数调用,直到日志记录模块确定将发出消息。
For example: 例如:
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))
The logging module is also kind enough to preserve the line on which the log call was actually made if there is ever an error. 如果出现错误,日志记录模块也足以保留实际进行日志调用的行。
logging.info(CallableMsg(math.factorial, -1))
Outputs: 输出:
--- 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: ()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.