gpt4 book ai didi

python - 在自定义类中包装记录器功能时显示正确的 funcName

转载 作者:IT老高 更新时间:2023-10-28 20:48:41 26 4
gpt4 key购买 nike

这是我用于记录的格式化字符串:

'%(asctime)s - %(levelname)-10s - %(funcName)s - %(message)s'

但是为了显示日志消息,我有一个包装器做更多的事情(我设置了不同的日志级别,配置不同的日志后端,提供方便的函数来访问自定义级别等):

class MyLogger(logging.Logger):

def split_line(self, level, message):
....
self.log.(level, line)

def progress(self, message):
self.split_line(PROGRESS, message)

有了这个设置,每当我记录一些东西时:

def myfunc():
log.progress('Hello')

我明白了:

013-10-27 08:47:30,130 - PROGRESS   - split_line - Hello

这不是我想要的,即:

013-10-27 08:47:30,130 - PROGRESS   - myfunc     - Hello

如何告诉记录器为函数名称使用正确的上下文?我认为这实际上会比 stackframe 高两个级别。

编辑

这是一个显示问题的测试程序:

import sys
import logging

PROGRESS = 1000

class MyLogger(logging.Logger):

PROGRESS = PROGRESS
LOG_FORMATTER = '%(asctime)s - %(levelname)-10s - %(funcName)s - %(message)s'
DEF_LOGGING_LEVEL = logging.WARNING

def __init__(self, log_name, level=None):
logging.Logger.__init__(self, log_name)
self.formatter = logging.Formatter(self.LOG_FORMATTER)
self.initLogger(level)

def initLogger(self, level=None):
self.setLevel(level or self.DEF_LOGGING_LEVEL)
self.propagate = False

def add_handler(self, log_file, use_syslog):
if use_syslog : hdlr = logging.handlers.SysLogHandler(address='/dev/log')
elif log_file : hdlr = logging.FileHandler(log_file)
else : hdlr = logging.StreamHandler(sys.stderr)
hdlr.setFormatter(self.formatter)
self.addHandler(hdlr)
return hdlr

def addHandlers(self, log_file=None, progress_file=None, use_syslog=False):
self.logger_hdlr = self.add_handler(log_file, use_syslog)
if progress_file:
self.progress_hdlr = self.add_handler(progress_file, use_syslog)
self.progress_hdlr.setLevel(self.PROGRESS)
else:
self.progress_hdlr = None

def split_line(self, level, txt, *args):
txt = txt % (args)
for line in txt.split('\n'):
self.log(level, line)

def progress(self, txt, *args):
self.split_line(self.PROGRESS, txt, *args)

logging.setLoggerClass(MyLogger)
logging.addLevelName(PROGRESS, 'PROGRESS')
logger = logging.getLogger(__name__)
logger.addHandlers()

name = 'John'
logger.progress('Hello %s\nHow are you doing?', name)

生产:

2013-10-27 09:47:39,577 - PROGRESS   - split_line - Hello John
2013-10-27 09:47:39,577 - PROGRESS - split_line - How are you doing?

最佳答案

本质上,应该归咎于 Logger 类的代码:

这个方法

def findCaller(self):
"""
Find the stack frame of the caller so that we can note the source
file name, line number and function name.
"""
f = currentframe()
#On some versions of IronPython, currentframe() returns None if
#IronPython isn't run with -X:Frames.
if f is not None:
f = f.f_back
rv = "(unknown file)", 0, "(unknown function)"
while hasattr(f, "f_code"):
co = f.f_code
filename = os.path.normcase(co.co_filename)
if filename == _srcfile:
f = f.f_back
continue
rv = (co.co_filename, f.f_lineno, co.co_name)
break
return rv

返回调用者链中不属于当前模块的第一个函数。

您可以继承 Logger 并通过添加稍微复杂的逻辑来覆盖此方法。跳过另一个级别的调用深度或添加另一个条件。


在您非常特殊的情况下,避免自动行拆分可能会更简单

logger.progress('Hello %s', name)
logger.progress('How are you doing?')

或去做

def splitter(txt, *args)
txt = txt % (args)
for line in txt.split('\n'):
yield line

for line in splitter('Hello %s\nHow are you doing?', name):
logger.progress(line)

并且有一个

def progress(self, txt, *args):
self.log(self.PROGRESS, txt, *args)

可能会省去很多麻烦。

编辑 2:不,这无济于事。它现在会将 progress 显示为您的调用者函数名称...

关于python - 在自定义类中包装记录器功能时显示正确的 funcName,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19615876/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com