Python handlers.TimedRotatingFileHandler 旋转不能按我预期的那样工作

Mar*_*tti 1 logging python-3.x

我需要文件轮换恰好在小时更改时发生,而不是在程序启动一小时后发生。

PS:我把在写日志的关怀<hour>:59:58<hour+1>:00:02以避免等待下一个写。

是否可以?

[handler_file_handler]
class=handlers.TimedRotatingFileHandler
level=INFO
formatter=formatter
delay=False
args=('logfile.log', 'H', 1, 0)
Run Code Online (Sandbox Code Playgroud)

Mar*_*ers 5

TimedRotatingFileHandler文档告诉您它使用与当前时间的偏移量;唯一的例外是工作日和每日选项(W0-W6midnight),它们atTime用作翻转的时间点:

当第一次计算下一次翻转时间时(当处理程序被创建时),现有日志文件的最后修改时间,或者当前时间,用于计算下一次轮换发生的时间。

[...]

如果atTime不是None,则它必须是datetime.time指定发生翻转的时间的实例,对于翻转设置为“午夜”或“特定工作日”发生的情况。请注意,在这些情况下,该atTime值有效地用于计算初始翻转,后续翻转将通过正常间隔计算进行计算。

如果必须进行循环翻转小时,一小时,那么你有两种选择:

  • 创建一个初始日志文件,mtime修改值设置为最近的整小时。这将用于将当前条目写入其中,并将从设置的修改时间旋转整整一个小时。
  • 提供一个替代TimedRotatingFileHandler.computeRollover()实现,它返回下一整小时的时间戳,而不仅仅是当前时间 + 间隔。

后者可能是这里更好的路径;将当前时间四舍五入到最接近的self.interval倍数很简单:

from logging.handlers import TimedRotatingFileHandler

class WholeIntervalRotatingFileHandler(TimedRotatingFileHandler):
    def computeRollover(self, currentTime):
        if self.when[0] == 'W' or self.when == 'MIDNIGHT':
            # use existing computation
            return super().computeRollover(currentTime)
        # round time up to nearest next multiple of the interval
        return ((currentTime // self.interval) + 1) * self.interval
Run Code Online (Sandbox Code Playgroud)

这会将下一次翻转时间计算为间隔的精确倍数。考虑到,如果你设置了interval参数类的值其他不是1那么接下来的整个间隔时间值可以是不同的; interval=2将选择可被 2 整除的下一个整小时,将其设置为0.5您会在整个半小时内看到旋转。

要在fileConfig配置文件中使用上述内容,只需将代码放在位于模块搜索路径上的模块中,然后class=modulename.WholeIntervalRotatingFileHandler在您的处理程序部分中使用。

演示显示下一个计算的翻转时间确实是下一个整小时:

>>> from datetime import datetime
>>> print(datetime.now())   # current time
2018-11-17 16:48:08.793855
>>> handler = WholeIntervalRotatingFileHandler('/tmp/logfile.log', 'H', 1, 0)
>>> print(datetime.fromtimestamp(handler.rolloverAt))  # next rotation time
2018-11-17 17:00:00
Run Code Online (Sandbox Code Playgroud)