如何解决 Python 中的日志轮转和压缩问题

40 阅读3分钟

在我编写的一个 Python 脚本中,我使用日志轮转和压缩功能,以便将脚本的日志信息记录到文件中。但是,我遇到了以下几个问题:

  1. 某些操作的日志没有记录到文件中,而是直接输出到控制台。
  2. 日志系统创建了三个日志文件,而不是一个。

2、解决方案

第一部分:解决某些操作的日志没有记录到文件中的问题

  1. 首先,我需要找出哪些操作的日志没有记录到文件中。
  2. 通过查看脚本的代码,我发现这些操作都是通过 subprocess.call() 函数调用的。
  3. 问题的原因是 subprocess.call() 函数不会将子进程的输出自动记录到日志文件中。
  4. 为了解决这个问题,我需要在调用 subprocess.call() 函数时指定 stdout 参数,并将其设置为我创建的日志处理器的输出流。

第二部分:解决日志系统创建了三个日志文件而不是一个的问题

  1. 我需要修改日志处理器的配置,以便它只创建一个日志文件。
  2. 通过查看日志处理器的文档,我了解到我可以通过设置 maxBytes 参数来限制日志文件的大小。
  3. 将 maxBytes 参数设置为一个较大的值,这样可以确保日志文件不会很快达到最大值,从而导致新的日志文件被创建。

代码例子

以下是修改后的脚本代码:

import time
import re
import os
import stat
import logging
import logging.handlers as handlers

class SizedTimedRotatingFileHandler(handlers.TimedRotatingFileHandler):
    """
    Handler for logging to a set of files, which switches from one file
    to the next when the current file reaches a certain size, or at certain
    timed intervals
    """
    def __init__(self, filename, mode='a', maxBytes=0, backupCount=0, encoding=None,
                 delay=0, when='h', interval=1, utc=False):
        # If rotation/rollover is wanted, it doesn't make sense to use another
        # mode. If for example 'w' were specified, then if there were multiple
        # runs of the calling application, the logs from previous runs would be
        # lost if the 'w' is respected, because the log file would be truncated
        # on each run.
        if maxBytes > 0:
            mode = 'a'
        handlers.TimedRotatingFileHandler.__init__(
            self, filename, when, interval, backupCount, encoding, delay, utc)
        self.maxBytes = maxBytes

    def shouldRollover(self, record):
        """
        Determine if rollover should occur.

        Basically, see if the supplied record would cause the file to exceed
        the size limit we have.
        """
        if self.stream is None:                 # delay was set...
            self.stream = self._open()
        if self.maxBytes > 0:                   # are we rolling over?
            msg = "%s\n" % self.format(record)
            self.stream.seek(0, 2)  #due to non-posix-compliant Windows feature
            if self.stream.tell() + len(msg) >= self.maxBytes:
                return 1
        t = int(time.time())
        if t >= self.rolloverAt:
            return 1
        return 0

if __name__ == '__main__':      

    #log to a file
    log_filename='/opt/log/importData.log'
    logger=logging.getLogger('importData')
    logger.setLevel(logging.DEBUG)
    handler=SizedTimedRotatingFileHandler(
        log_filename, maxBytes=10485760, backupCount=5,
        when='s',interval=10,
        # encoding='bz2',  # uncomment for bz2 compression
    )
    formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
    handler.setFormatter(formatter)
    logger.addHandler(handler)

    #--- constant connection values
    ftpServerName = "xxxxx.xxxxxx"
    ftpU = "xxxxxxxx"
    ftpP = "xxxxxx"
    remoteDirectoryPath = "/xxxxxx/xxxxxx/xxxxxx/xxxxxxx/"
    localDirectoryPath = "/xxxxx/xxxxxxxxx/xxxxxxxx/xxxxxxx/"

    directory = '/xxxxxxx/'
    filematch = '*.xml'
    source='/xxxxxx/xxxxxxxx/'
    destination='/xxxxxxxx/xxxxxx/'

    deleteAfterCopy = False     #set to true if you want to clean out the remote directory
    onlyNewFiles = True         #set to true to grab & overwrite all files locally
    importData(ftpServerName,ftpU,ftpP,directory,filematch,source,destination)
    moveFTPFiles(ftpServerName,ftpU,ftpP,remoteDirectoryPath,localDirectoryPath,deleteAfterCopy,onlyNewFiles)

importData.log:

2015-04-23 11:33:57,408 INFO Files Moved: 1145 on Thu 23 Apr 2015  11:33:57 AM

importData.log.2015-04-23_11-33-40:

2015-04-23 11:33:40,896 INFO  Deleting Files  2015-04-23 11:33:40,956
  INFO  Retreiving Files

importData.log2015-04-23_11-33-41:

2015-04-23 11:33:41,386 INFO  Connecting  2015-04-23 11:33:41,825 INFO
  Missing 1145

通过上述修改,我成功地解决了脚本中的日志问题。现在,所有的操作日志都会被记录到文件中,并且日志文件的大小不会超过指定的限制。