Python RotatingFileHandler似乎没有旋转日志

时间:2018-06-05 10:04:31

标签: python logging

我使用以下代码设置了一个记录器:

log = logging.getLogger('base')
logfilename =  <path to logfile>
logFile = logging.FileHandler(logfilename)
log.setLevel(debug)
logFile.setFormatter(logging.Formatter('[%(asctime)s]: [%(filename)s:%(lineno)d:%(funcName)s]: %(levelname)s :: %(message)s', datefmt='%m-%d-%Y %H:%M:%S'))
log.addHandler(logFile)

由于日志文件很大,我想创建一个旋转日志文件。 因此我做了以下改变:

# logFile = logging.FileHandler(logfilename)
logFile = RotatingFileHandler(logfilename, maxBytes=1024)  # maxBytes=1024 only for testing

但是,生成的日志文件未被轮换。我仍然得到几MB大的日志。我已清除所有.pyc个文件。

问题:

  1. 是否有必要指定备份计数(我需要保留所有日志!因此,如果这是强制性的,我必须提供一些非常大的数字)。
  2. maxBytes我假设它是实际的字节数(因此在我的情况下,日志应该每1 kB旋转一次),而不是其他任何内容。我是对的吗?
  3. maxBytes以下的最小数字是否在旋转无效? (我想不是)
  4. 我使用Python 2.7.14(Anaconda)和3.6.4(Anaconda)。

2 个答案:

答案 0 :(得分:1)

来自docs

  

如果maxBytes或backupCount中的任何一个为零,则不会发生翻转,   所以你通常想把backupCount设置为至少1,并且有一个   非零maxBytes。

这意味着如果不设置backupCount(默认值为0),您将无法获得任何翻转功能

  

我需要保留所有日志!因此,如果这是强制性的,我必须给予   一些疯狂的大数

是的!设置一些非常大的数字,并且可能每隔一段时间添加另一个脚本来备份旧文件

答案 1 :(得分:1)

您需要设置backupCount值,更改文件模式,而不是在打开时附加截断。

日志文件 已关闭,但再次重新打开以附加,因此您实际上从未看到过差异。

现在发生的事情是:

  • 处理程序测试当前文件长度加上消息是否将文件长度超过最大值。
    • 如果长度超过最大值,请关闭文件
    • 如果backupCount大于零,请轮换所有现有备份文件,然后重命名日志文件以添加.1
    • 打开日志文件以进行追加。如果已存在具有相同名称的文件,则重新打开该文件。
  • 将邮件写入打开的日志文件。

除了将backupCount设置为高于0的数字之外,您还可以将mode参数更改为'w',此时您会发现该文件是每次变得过大时都会被截断

# 'rotate' logfile by truncating:
logFile = RotatingFileHandler(logfilename, mode='w', maxBytes=1024)

请注意,如果新邮件本身长度超过1024个字节,则文件仍可能大于maxBytes

没有选项可以保留所有旋转的文件。你确实必须使用一个非常高的数字,使用不同的文件轮换策略。例如,TimedRotatingFileHandler在给定的时间间隔后旋转文件,如果将backupCount保留为零,则永远不会删除已轮换的备份。

您还可以将RotatingFileHandler()子类化以实现您自己的重命名策略,并提供您自己的doRollover()方法。如果要保留所有备份,则需要生成唯一的名称;你可以添加一个UUID来确保这一点(连同日期):

import uuid
from datetime import datetime
from logging import RotatingFileHandler

class InfiniteRotatingFileHandler(RotatingFileHandler):
    def doRollover(self):
        if self.stream:
            self.stream.close()
            self.stream = None
        new_name = '{}.{:%Y%m%d%H%M%S}.{}'.format(
            self.baseFilename, datetime.now(), uuid.uuid4())
        self.rotate(self.baseFilename, new_name)
        if not self.delay:
            self.stream = self._open()