【发布时间】:2010-10-23 04:27:21
【问题描述】:
也许它只是不存在,因为我找不到它。但是使用python的日志包,有没有办法查询一个记录器来找出一个特定的函数被调用了多少次?例如,报告了多少错误/警告?
【问题讨论】:
也许它只是不存在,因为我找不到它。但是使用python的日志包,有没有办法查询一个记录器来找出一个特定的函数被调用了多少次?例如,报告了多少错误/警告?
【问题讨论】:
日志模块似乎不支持这一点。从长远来看,您最好创建一个新模块,并通过对现有日志记录模块中的项目进行子类化来添加此功能以添加您需要的功能,但您也可以使用装饰器轻松实现此行为:
class CallCounted:
"""Decorator to determine number of calls for a method"""
def __init__(self,method):
self.method=method
self.counter=0
def __call__(self,*args,**kwargs):
self.counter+=1
return self.method(*args,**kwargs)
import logging
logging.error = CallCounted(logging.error)
logging.error('one')
logging.error('two')
print(logging.error.counter)
输出:
ERROR:root:one
ERROR:root:two
2
【讨论】:
您还可以向记录所有调用的记录器添加一个新的处理程序:
class MsgCounterHandler(logging.Handler):
level2count = None
def __init__(self, *args, **kwargs):
super(MsgCounterHandler, self).__init__(*args, **kwargs)
self.level2count = {}
def emit(self, record):
l = record.levelname
if (l not in self.level2count):
self.level2count[l] = 0
self.level2count[l] += 1
之后您可以使用 dict 来输出调用次数。
【讨论】:
基于Rolf's answer 和how to write a dictionary to a file,这里是另一种将计数存储在json 文件中的解决方案。如果 json 文件存在且 continue_counts=True,它会恢复初始化计数。
import json
import logging
import logging.handlers
import os
class MsgCounterHandler(logging.Handler):
"""
A handler class which counts the logging records by level and periodically writes the counts to a json file.
"""
level2count_dict = None
def __init__(self, filename, continue_counts=True, *args, **kwargs):
"""
Initialize the handler.
PARAMETER
---------
continue_counts: bool, optional
defines if the counts should be loaded and restored if the json file exists already.
"""
super(MsgCounterHandler, self).__init__(*args, **kwargs)
filename = os.fspath(filename)
self.baseFilename = os.path.abspath(filename)
self.continue_counts = continue_counts
# if another instance of this class is created, get the actual counts
if self.level2count_dict is None:
self.level2count_dict = self.load_counts_from_file()
def emit(self, record):
"""
Counts a record.
In case, create add the level to the dict.
If the time has come, update the json file.
"""
level = record.levelname
if level not in self.level2count_dict:
self.level2count_dict[level] = 0
self.level2count_dict[level] += 1
self.flush()
def flush(self):
"""
Flushes the dictionary.
"""
self.acquire()
try:
json.dump(self.level2count_dict, open(self.baseFilename, 'w'))
finally:
self.release()
def load_counts_from_file(self):
"""
Load the dictionary from a json file or create an empty dictionary
"""
if os.path.exists(self.baseFilename) and self.continue_counts:
try:
level2count_dict = json.load(open(self.baseFilename))
except Exception as a:
logging.warning(f'Failed to load counts with: {a}')
level2count_dict = {}
else:
level2count_dict = {}
return level2count_dict
【讨论】: