我不相信一个管理者是你的解决方案。选择过滤器:
import os.path
import traceback
import logging
_LOGGING_FILE = os.path.normcase(logging.addLevelName.__code__.co_filename)
_CURRENT_FILE = os.path.normcase(__file__)
_ELIMINATE_STACK = (_CURRENT_FILE, _LOGGING_FILE)
class AddStackFilter(logging.Filter):
def __init__(self, levels=None):
self.levels = levels or set()
def get_stack(self):
# Iterator over file names
filenames = iter(_ELIMINATE_STACK)
filename = next(filenames, "")
frames = traceback.walk_stack(None)
# Walk up the frames
for frame, lineno in frames:
# If frame is not from file, continue on to the next file
while os.path.normcase(frame.f_code.co_filename) != filename:
filename = next(filenames, None)
if filename is None:
break
else:
# It's from the given file, go up a frame
continue
# Finished iterating over all files
break
# No frames left
else:
return None
info = traceback.format_stack(frame)
info.insert(0, 'Stack (most recent call last):\n')
# Remove last newline
info[-1] = info[-1].rstrip()
return "".join(info)
def filter(self, record):
if record.levelno in self.levels:
sinfo = self.get_stack()
if sinfo is not None:
record.stack_info = sinfo
return True
此过滤器有许多优点:
-
从本地文件和日志记录文件中删除堆栈帧。
-
留下堆栈帧,以防在通过日志记录后返回到本地文件。重要的是,如果我们希望将同一个模块用于其他内容。
-
您可以将它附加到任何处理程序或记录器,而不会将您绑定到streamhandler或任何其他处理程序。
-
您可以使用相同的筛选器或单个处理程序影响多个处理程序。
-
等级表示为
__init__
变量,允许您根据需要添加更多级别。
-
允许您将堆栈跟踪添加到日志中,而不仅仅是打印。
-
很好地处理日志模块,将堆栈放在正确的位置,没有什么意外。
用途:
>>> import stackfilter
>>> import logging
>>> sfilter = stackfilter.AddStackFilter(levels={logging.WARNING})
>>> logging.basicConfig()
>>> logging.getLogger().addFilter(sfilter)
>>> def testy():
... logging.warning("asdasd")
...
>>> testy()
WARNING:root:asdasd
Stack (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in testy