我正在使用python 3中的def canned_example():
logger.warning("This function hasn't been created yet")
for i in range(10):
canned_example()
模块,并希望特定的警告消息只显示一次。
问题是检查是在循环内:
def canned_example():
logger.warning("This function hasn't been created yet", norepeat=True)
for i in range(10):
canned_example()
是否在日志记录模块中设置了一个标志,表示此特定警告只显示一次?另一种方法是保留不同标志的记录,但如果可能的话,我想保持简单。
更新:Amir Yazdanbakhsh在评论中发布了一个答案,允许我们对所有邮件执行此操作。理想情况下,我想要一些每消息标志:
{{1}}
答案 0 :(得分:5)
定义一个过滤器,用于跟踪记录的内容,并在循环期间将其附加到记录器。此示例将记住它看到的每条消息,并且只允许记录第一个匹配项。
class DuplicateFilter(object):
def __init__(self):
self.msgs = set()
def filter(self, record):
rv = record.msg not in self.msgs
self.msgs.add(record.msg)
return rv
dup_filter = DuplicateFilter()
logger.addFilter(dup_filter)
for i in range(10):
canned_example()
logger.removeFilter(dup_filter)
答案 1 :(得分:4)
“误用”functools
lru_cache 是一个小技巧,但要容易得多。
from functools import lru_cache
from logging import getLogger
# Keep track of 10 different messages and then warn again
@lru_cache(10)
def warn_once(logger: Logger, msg: str):
logger.warning(msg)
如果需要,您可以增加 10
以抑制更多,或将其设置为 None
以存储抑制所有重复的内容。
这个答案也完全满足了只抑制特定重复警告的要求,因为 logger.warning("message") 根本没有被过滤。
此外,此解决方案的内存效率更高,因为重复的日志不会多次保留在内存中。
答案 2 :(得分:2)
这是@chepner答案的修改后的变体。当记录的内容不是字符串(即异常)时,我遇到了一些问题,想使用上下文管理器更方便地添加和删除过滤器:
class DuplicateFilter:
"""
Filters away duplicate log messages.
Modified version of: https://stackoverflow.com/a/31953563/965332
"""
def __init__(self, logger):
self.msgs = set()
self.logger = logger
def filter(self, record):
msg = str(record.msg)
is_duplicate = msg in self.msgs
if not is_duplicate:
self.msgs.add(msg)
return not is_duplicate
def __enter__(self):
self.logger.addFilter(self)
def __exit__(self, exc_type, exc_val, exc_tb):
self.logger.removeFilter(self)
用法:
logger = logging.getLogger(__name__)
with DuplicateFilter(logger):
for _ in range(5):
logger.info("This will only show up once!")
logger.error(Exception("So will this!")) # This didn't work in @chepner's example