在使用 time-rotating 记录器创建的每个日志文件中写入一个 header
Write a header at every logfile that is created with a time-rotating logger
我制作了一个 time-rotating 记录器,它会在午夜创建一个新的日志文件。在我的日志文件中,我想在每个文件的顶部写一个 header 。我正在寻找一种有效的方法来调用一个函数,该函数在创建文件时将 header 写入日志文件。
import logging
from logging.handlers import TimedRotatingFileHandler
# create time-rotating log handler
logHandler = TimedRotatingFileHandler(logfile, when='midnight')
# create logger
self.log = logging.getLogger('MyTimeRotatingLogger')
self.log.addHandler(logHandler)
我解决了!基本上所有需要做的就是覆盖 TimedRotatingFileHandler
的 doRollover
方法,在这个新的 parent class 中也需要一些代码来传递日志实例和设置 header 内容。特此为遇到类似情况的人提供一个广泛的例子。
from logging.handlers import TimedRotatingFileHandler
class MyTimedRotatingFileHandler(TimedRotatingFileHandler):
def __init__(self, logfile, when, interval):
super(MyTimedRotatingFileHandler, self).__init__(logfile, when, interval)
self._header = ""
self._log = None
def doRollover(self):
super(MyTimedRotatingFileHandler, self).doRollover()
if self._log is not None and self._header != "":
self._log.info(self._header)
def setHeader(self, header):
self._header = header
def configureHeaderWriter(self, header, log):
self._header = header
self._log = log
# create time-rotating log handler
logHandler = MyTimedRotatingFileHandler(logfile, when='midnight')
form = '%(asctime)s %(name)s %(levelname)s: %(message)s'
logFormatter = logging.Formatter(form)
logHandler.setFormatter(logFormatter)
# create logger
log = logging.getLogger('MyLogger')
logHandler.configureHeaderWriter('test-header', log)
log.addHandler(logHandler)
log.setLevel(logging.INFO)
为了在第一个日志文件中也有一个 header,我建议对您的解决方案进行稍微修改的替代方案。即,在定义 header 之后立即对写入 header 的代码段进行额外调用,并在记录器设置中插入某些行(请参阅代码中的注释):
from logging.handlers import TimedRotatingFileHandler
class MyTimedRotatingFileHandler(TimedRotatingFileHandler):
def __init__(self, logfile, when, interval):
super(MyTimedRotatingFileHandler, self).__init__(logfile, when, interval)
self._header = ""
self._log = None
def write_header(self):
if self._log is not None and self._header != '':
self._log.info(self._header)
def doRollover(self):
super(MyTimedRotatingFileHandler, self).doRollover()
self.write_header()
def configureHeaderWriter(self, header, log):
self._header = header
self._log = log
self.write_header() # WRITE HEADER TO FIRST FILE
# create time-rotating log handler
logHandler = MyTimedRotatingFileHandler(logfile, when='midnight')
form = '%(asctime)s %(name)s %(levelname)s: %(message)s'
logFormatter = logging.Formatter(form)
logHandler.setFormatter(logFormatter)
# create logger
log = logging.getLogger('MyLogger')
# CONFIGURE LOG LEVEL AND ATTACH HANDLER TO LOGGER **BEFORE** SETTING THE HEADER
log.setLevel(logging.INFO)
log.addHandler(logHandler)
logHandler.configureHeaderWriter('test-header', log)
上面的解决方案涵盖了大多数用例,但如果您仍想尊重 FileHandler.delay
属性的行为,我认为最简单的解决方案是重写 _open()
方法:
class MyTimedRotatingFileHandler(TimedRotatingFileHandler):
def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False, atTime=None, header=''):
self.header = header
super().__init__(filename, when, interval, backupCount, encoding, delay, utc, atTime)
def _open(self):
stream = super()._open()
if self.header and stream.tell() == 0:
stream.write(self.header + self.terminator)
stream.flush()
return stream
这样您就可以避免以仅包含 header 的“空”日志文件结束,并且您不必担心将特定记录器传递给处理程序。
我制作了一个 time-rotating 记录器,它会在午夜创建一个新的日志文件。在我的日志文件中,我想在每个文件的顶部写一个 header 。我正在寻找一种有效的方法来调用一个函数,该函数在创建文件时将 header 写入日志文件。
import logging
from logging.handlers import TimedRotatingFileHandler
# create time-rotating log handler
logHandler = TimedRotatingFileHandler(logfile, when='midnight')
# create logger
self.log = logging.getLogger('MyTimeRotatingLogger')
self.log.addHandler(logHandler)
我解决了!基本上所有需要做的就是覆盖 TimedRotatingFileHandler
的 doRollover
方法,在这个新的 parent class 中也需要一些代码来传递日志实例和设置 header 内容。特此为遇到类似情况的人提供一个广泛的例子。
from logging.handlers import TimedRotatingFileHandler
class MyTimedRotatingFileHandler(TimedRotatingFileHandler):
def __init__(self, logfile, when, interval):
super(MyTimedRotatingFileHandler, self).__init__(logfile, when, interval)
self._header = ""
self._log = None
def doRollover(self):
super(MyTimedRotatingFileHandler, self).doRollover()
if self._log is not None and self._header != "":
self._log.info(self._header)
def setHeader(self, header):
self._header = header
def configureHeaderWriter(self, header, log):
self._header = header
self._log = log
# create time-rotating log handler
logHandler = MyTimedRotatingFileHandler(logfile, when='midnight')
form = '%(asctime)s %(name)s %(levelname)s: %(message)s'
logFormatter = logging.Formatter(form)
logHandler.setFormatter(logFormatter)
# create logger
log = logging.getLogger('MyLogger')
logHandler.configureHeaderWriter('test-header', log)
log.addHandler(logHandler)
log.setLevel(logging.INFO)
为了在第一个日志文件中也有一个 header,我建议对您的解决方案进行稍微修改的替代方案。即,在定义 header 之后立即对写入 header 的代码段进行额外调用,并在记录器设置中插入某些行(请参阅代码中的注释):
from logging.handlers import TimedRotatingFileHandler
class MyTimedRotatingFileHandler(TimedRotatingFileHandler):
def __init__(self, logfile, when, interval):
super(MyTimedRotatingFileHandler, self).__init__(logfile, when, interval)
self._header = ""
self._log = None
def write_header(self):
if self._log is not None and self._header != '':
self._log.info(self._header)
def doRollover(self):
super(MyTimedRotatingFileHandler, self).doRollover()
self.write_header()
def configureHeaderWriter(self, header, log):
self._header = header
self._log = log
self.write_header() # WRITE HEADER TO FIRST FILE
# create time-rotating log handler
logHandler = MyTimedRotatingFileHandler(logfile, when='midnight')
form = '%(asctime)s %(name)s %(levelname)s: %(message)s'
logFormatter = logging.Formatter(form)
logHandler.setFormatter(logFormatter)
# create logger
log = logging.getLogger('MyLogger')
# CONFIGURE LOG LEVEL AND ATTACH HANDLER TO LOGGER **BEFORE** SETTING THE HEADER
log.setLevel(logging.INFO)
log.addHandler(logHandler)
logHandler.configureHeaderWriter('test-header', log)
上面的解决方案涵盖了大多数用例,但如果您仍想尊重 FileHandler.delay
属性的行为,我认为最简单的解决方案是重写 _open()
方法:
class MyTimedRotatingFileHandler(TimedRotatingFileHandler):
def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False, atTime=None, header=''):
self.header = header
super().__init__(filename, when, interval, backupCount, encoding, delay, utc, atTime)
def _open(self):
stream = super()._open()
if self.header and stream.tell() == 0:
stream.write(self.header + self.terminator)
stream.flush()
return stream
这样您就可以避免以仅包含 header 的“空”日志文件结束,并且您不必担心将特定记录器传递给处理程序。