如何使日志记录装饰器记录文件名的使用位置而不是定义位置?



我使用具有filename格式的logging模块来捕获代码的日志输出。这很好,因为现在我总是知道消息是从哪个文件发送的。但是,我有一个缩进日志装饰器,我想为它实际记录使用的文件名,而不是定义装饰器所在的模块。这可能吗?

以下是它现在正在做的一个简短的例子:

test.py

import logging
from log import logger
from log import indented
@indented('Here I start my method...', 'And here it ends')
def my_func():
logger.info('Look, a message!')

if __name__ == '__main__':
logging.basicConfig(
filename='LOG',
level=logging.DEBUG,
format='%(asctime)s.%(msecs)03d [ %(levelname)-8s] %(filename)s: %(message)s',
datefmt="%Y-%m-%d %H:%M:%S")
my_func()

日志输出

2018-07-27 13:27:15.541 [ INFO    ] log.py: Here I start my method...
2018-07-27 13:27:15.541 [ INFO    ] test.py: ---- Look, a message!
2018-07-27 13:27:15.541 [ INFO    ] log.py: And here it ends

现在我希望所有三条消息都包含test.py,如下所示:

所需输出

2018-07-27 13:27:15.541 [ INFO    ] test.py: Here I start my method...
2018-07-27 13:27:15.541 [ INFO    ] test.py: ---- Look, a message!
2018-07-27 13:27:15.541 [ INFO    ] test.py: And here it ends

log.py

import logging
from contextlib import contextmanager
from functools import wraps

class IndentationAdapter(logging.LoggerAdapter):
def __init__(self, logger, extra):
super().__init__(logger, extra)
self._indent = 0
def indent(self):
self._indent += 4
def dedent(self):
self._indent -= 4
def process(self, msg, kwargs):
if self._indent > 0:
return '{i} {m}'.format(i='-'*self._indent, m=msg), kwargs
else:
return msg, kwargs
logger = IndentationAdapter(logging.getLogger(), {})
@contextmanager
def indent_logging():
logger.indent()
try:
yield
finally:
logger.dedent()

def indented(begin_message, end_message):
def indent_decorator(func):
@wraps(func)
def func_wrapper(*args, **kwargs):
logger.info(begin_message)
with indent_logging():
output = func(*args, **kwargs)
logger.info(end_message)
return output
return func_wrapper
return indent_decorator

我能够通过复制标准库的日志记录模块使用的一些代码检查来自动化文件名和开始/结束消息。我删除了手册的开始和结束信息,认为这更符合您的意图。我还从日志格式中删除了filename,并将其添加到indent_decorator记录的文本中。

def indented():
def indent_decorator(func):
@wraps(func)
def func_wrapper(*args, **kwargs):
filename = os.path.basename(func.__code__.co_filename)
logger.info(filename + ': begin ' + func.__name__)
with indent_logging():
output = func(*args, **kwargs)
logger.info(filename + ': end ' + func.__name__)
return output
return func_wrapper
return indent_decorator

这是日志输出

2018-12-31 08:14:25.536 [ INFO    ] test.py: begin my_func
2018-12-31 08:14:25.536 [ INFO    ] ---- Look, a message!
2018-12-31 08:14:25.536 [ INFO    ] test.py: end my_func

我不知道我们能在多大程度上依赖代码在未来版本的python中保持不变,但这在3.6.5 中对我有效

我怀疑它应该被进一步简化,这样你就不必在装饰器上放parens,所以这可能是以后的编辑。

最新更新