我正在处理的旧代码库中有多个logging.warn('....')
调用。
我想更好地了解日志输出。到目前为止,logging.warn()
确实发出了一行。但是,仅此一行不足以理解上下文。
我想查看解释器的堆栈跟踪。
由于我的代码中有很多logging.warn('....')
行,因此我想保留它们,只修改日志记录的配置。
如何将解释器堆栈跟踪自动添加到每个warn()
或error()
调用中?
我知道logging.exception("message")
显示了堆栈跟踪,但是我想保留logging.warn()
行。
答案 0 :(得分:2)
如果您接受添加日志处理程序,那就太简单了:
import logging
import traceback
class WarnWithStackHandler(logging.StreamHandler):
def emit(self, record):
if record.levelno == logging.WARNING:
stack = traceback.extract_stack()
# skip logging internal stacks
stack = stack[:-7]
for line in traceback.format_list(stack):
print(line, end='')
super().emit(record)
答案 1 :(得分:1)
我不认为处理程序是您的解决方案。进行过滤:
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
此过滤器具有很多优点:
__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
答案 2 :(得分:1)
@Martijn Pieters♦在评论中给出了我一直在寻找的答案
在python 3.x中
logger.warning(f'{error_message}', stack_info=True)
完全满足您的需求。
感谢@Martijn Pieters♦