我正在使用基本的日志记录python模块添加日志。
我决定如下创建一个名为Log.py
的日志类:
class Log:
def __init__(self, path):
self.LOGGER = logging.getLogger('Open-Capture')
if self.LOGGER.hasHandlers():
self.LOGGER.handlers.clear() # Clear the handlers to avoid double logs
logFile = RotatingFileHandler(path, mode='a', maxBytes=5 * 1024 * 1024,
backupCount=2, encoding=None, delay=0)
formatter = logging.Formatter('[%(threadName)-14s] [%(filename)s:%(lineno)-15s] %(asctime)s %(levelname)s %(message)s', datefmt='%d-%m-%Y %H:%M:%S')
logFile.setFormatter(formatter)
self.LOGGER.addHandler(logFile)
self.LOGGER.setLevel(logging.DEBUG)
def info(self, msg):
self.LOGGER.info(msg)
def error(self, msg):
self.LOGGER.error(msg)
如您所见,我使用%(filename)s:%(lineno)
变量来增加更多的可读性。但是在我的日志文件中,我有Log.py:34
而不是源文件的文件名和行号,因为在我登录时,我这样称呼它:
Log = Log(Config.cfg['GLOBAL']['logfile'])
Log.info('test log')
是否可以将源文件而不是Log.py
保留在日志文件中?
预先感谢
答案 0 :(得分:1)
是的,有可能,通过我非常肯定我在这里发布的实现不是100%安全的,并确保有更好/更优雅的实现,以此为提示。
要获取调用方的文件名和行号,您可以使用inspect
模块,将这些自定义信息添加到日志中,可以添加自定义Filter
:
import logging
from logging.handlers import RotatingFileHandler
from inspect import getframeinfo, stack
class CallerFilter(logging.Filter):
""" This class adds some context to the log record instance """
file = ''
line_n = ''
def filter(self, record):
record.file = self.file
record.line_n = self.line_n
return True
def caller_reader(f):
"""This wrapper updates the context with the callor infos"""
def wrapper(self, *args):
caller = getframeinfo(stack()[1][0])
self._filter.file = caller.filename
self._filter.line_n = caller.lineno
return f(self, *args)
return wrapper
class Log:
def __init__(self, path):
self.LOGGER = logging.getLogger('Open-Capture')
if self.LOGGER.hasHandlers():
self.LOGGER.handlers.clear() # Clear the handlers to avoid double logs
logFile = RotatingFileHandler(path, mode='a', maxBytes=5 * 1024 * 1024,
backupCount=2, encoding=None, delay=0)
formatter = logging.Formatter('[%(threadName)-14s] [%(file)s:%(line_n)-15s] %(asctime)s %(levelname)s %(message)s', datefmt='%d-%m-%Y %H:%M:%S')
logFile.setFormatter(formatter)
self.LOGGER.addHandler(logFile)
# Here we add the Filter, think of it as a context
self._filter = CallerFilter()
self.LOGGER.addFilter(self._filter)
self.LOGGER.setLevel(logging.DEBUG)
@caller_reader
def info(self, msg):
self.LOGGER.info(msg)
@caller_reader
def error(self, msg):
self.LOGGER.error(msg)
from log import Log
log = Log('l.log')
log.info('LOG MESSAGE')
log.error('LOG MESSAGE 2 ')
log.info('LOG MESSAGE 2 ')
输出:
[MainThread ] [script_file.py:4 ] 17-01-2020 16:34:36 INFO LOG MESSAGE
[MainThread ] [script_file.py:5 ] 17-01-2020 16:34:36 ERROR LOG MESSAGE 2
[MainThread ] [script_file.py:6 ] 17-01-2020 16:34:36 INFO LOG MESSAGE 2