【问题标题】:Compact (archive) old log files in pythonpython中的压缩(归档)旧日志文件
【发布时间】:2011-10-24 00:41:47
【问题描述】:

我在 Python 中使用标准记录器库。例如,有 RotatingFileHandler,可以每天轮换日志文件。

但它只是重命名它们。如果它不仅可以重命名,而且还可以将旧文件放入 zip(或 gz、bzip 等)存档中,那就太好了。

有没有简单的方法来实现这一点?

【问题讨论】:

  • 子类化并实现它。

标签: python logging archive


【解决方案1】:

我认为您最好的选择是扩展 RotatingFileHandler 类似的东西(未测试):

import os
from logging.handlers import RotatingFileHandler


COMPRESSION_SUPPORTED = {}

try:
   import gzip
   COMPRESSION_SUPPORTED['gz'] = gzip
except ImportError:
   pass

try:
   import zipfile
   COMPRESSION_SUPPORTED['zip'] = zipfile
except ImportError:
   pass


class NewRotatingFileHandler(RotatingFileHandler):

     def __init__(self, *args, **kws):
         compress_mode = kws.pop('compress_mode')

         try:
             self.compress_cls = COMPRESSION_SUPPORTED[compress_mode]
         except KeyError:
             raise ValueError('"%s" compression method not supported.' % compress_mode)

         super(NewRotatingFileHandler, self).__init__(self, *args, **kws)

     def doRollover(self):
         super(NewRotatingFileHandler, self).doRollover()

         # Compress the old log.
         old_log = self.baseFilename + ".1"
         with open(old_log) as log:
             with self.compress_cls.open(old_log + '.gz', 'wb') as comp_log:
                 comp_log.writelines(log)

         os.remove(old_log)

【讨论】:

  • 看起来你的方法是目前最好的解决方案。谢谢。
  • ".1" 是什么意思?
  • @Cacheing 请参阅RotatingFileHandler 上的文档:“如果 backupCount 不为零,系统将通过附加扩展名 '.1'、'.2' 等来保存旧日志文件,以文件名。”
  • @dwurf 感谢您回答我的问题!
  • 这不能正确处理backupCount > 1,因为压缩文件没有正确重命名
【解决方案2】:

接受的答案将仅存档 1 个文件-(basefile.log.1) 。其他文件未存档。 此代码将归档除基本文件之外的所有日志文件。

import os
import gzip
import logging.handlers

class NewRotatingFileHandler(logging.handlers.RotatingFileHandler):
    def __init__(self, filename, **kws):
        backupCount = kws.get('backupCount', 0)
        self.backup_count = backupCount
        logging.handlers.RotatingFileHandler.__init__(self, filename, **kws)

    def doArchive(self, old_log):
        with open(old_log) as log:
            with gzip.open(old_log + '.gz', 'wb') as comp_log:
                comp_log.writelines(log)
       os.remove(old_log)

   def doRollover(self):
      if self.stream:
          self.stream.close()
          self.stream = None
      if self.backup_count > 0:
          for i in range(self.backup_count - 1, 0, -1):
              sfn = "%s.%d.gz" % (self.baseFilename, i)
              dfn = "%s.%d.gz" % (self.baseFilename, i + 1)
              if os.path.exists(sfn):
                  if os.path.exists(dfn):
                      os.remove(dfn)
                  os.rename(sfn, dfn)
      dfn = self.baseFilename + ".1"
      if os.path.exists(dfn):
          os.remove(dfn)
      if os.path.exists(self.baseFilename):
          os.rename(self.baseFilename, dfn)
          self.doArchive(dfn)
      if not self.delay:
          self.stream = self._open()

【讨论】:

    【解决方案3】:

    你可以通过encoding='bz2-codec'初始化RotatingFileHandler来自动写入bz2压缩日志文件:

    import logging
    import logging.handlers as handlers
    
    if __name__=='__main__':
        log_filename='log_rotate.bz2'
        logger = logging.getLogger(__name__)
        logger.setLevel(logging.DEBUG)
        handler = handlers.RotatingFileHandler(
            log_filename, maxBytes=20, backupCount=5, encoding='bz2-codec')
        logger.addHandler(handler)
        for i in range(20):
            logger.debug('i = %d' % i)
    

    PS。 Python3 removed 'bz2-codec' 来自有效编码集,因此此解决方案特定于 Python2。

    【讨论】:

    • 附加日志时是否有效?我预计不会,但尚未验证。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-30
    • 1970-01-01
    • 2015-08-15
    • 2021-10-10
    • 2016-02-08
    • 2013-12-04
    • 1970-01-01
    相关资源
    最近更新 更多