logging中RotatingFileHandler和TimedRotatingFileHandler对于多进程不支持(由于每个进程都保持一个固定的文件句柄,导致在达到条件回滚时,相互之间的rename会相互干扰,比如一个进程已经把worker.log变为worker.log.2016-06-01了,其他进程就跟着写到worker.log.2016-06-01了,其他还有好多问题)
故实现适应多进程的handle,代码如下:
# -*- coding: utf-8 -*- import logging, os, re, time, datetime try: import codecs except ImportError: codecs = None class MyLoggerHandler(logging.FileHandler): def __init__(self, filename, when=‘D‘, backupCount=0, encoding=None, delay=False): self.prefix = filename self.when = when.upper() # S - Every second a new file # M - Every minute a new file # H - Every hour a new file # D - Every day a new file if self.when == ‘S‘: self.suffix = "%Y-%m-%d_%H-%M-%S" self.extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}$" elif self.when == ‘M‘: self.suffix = "%Y-%m-%d_%H-%M" self.extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}$" elif self.when == ‘H‘: self.suffix = "%Y-%m-%d_%H" self.extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}$" elif self.when == ‘D‘: self.suffix = "%Y-%m-%d" self.extMatch = r"^\d{4}-\d{2}-\d{2}$" else: raise ValueError("Invalid rollover interval specified: %s" % self.when) self.filefmt = os.path.join("logs", "%s.%s" % (self.prefix, self.suffix)) self.filePath = datetime.datetime.now().strftime(self.filefmt) _dir = os.path.dirname(self.filePath) try: if os.path.exists(_dir) is False: os.makedirs(_dir) except Exception: print "can not make dirs" print "filepath is " + self.filePath pass self.backupCount = backupCount if codecs is None: encoding = None logging.FileHandler.__init__(self, self.filePath, ‘a‘, encoding, delay) def shouldChangeFileToWrite(self): _filePath = datetime.datetime.now().strftime(self.filefmt) if _filePath != self.filePath: self.filePath = _filePath return 1 return 0 def doChangeFile(self): self.baseFilename = os.path.abspath(self.filePath) if self.stream is not None: self.stream.flush() self.stream.close() if not self.delay: self.stream = self._open() if self.backupCount > 0: for s in self.getFilesToDelete(): os.remove(s) def getFilesToDelete(self): dirName, baseName = os.path.split(self.baseFilename) fileNames = os.listdir(dirName) result = [] prefix = self.prefix + "." plen = len(prefix) for fileName in fileNames: if fileName[:plen] == prefix: suffix = fileName[plen:] if re.compile(self.extMatch).match(suffix): result.append(os.path.join(dirName, fileName)) result.sort() if len(result) < self.backupCount: result = [] else: result = result[:len(result) - self.backupCount] return result def emit(self, record): """ Emit a record. """ try: if self.shouldChangeFileToWrite(): self.doChangeFile() logging.FileHandler.emit(self, record) except (KeyboardInterrupt, SystemExit): raise except: self.handleError(record)
使用方式和TimedRotatingFileHandler差不多,如文件配置按下:
[handler_workerFile2] class=log_kit.MyLoggerHandler level=INFO formatter=simpleFormatter args=(r‘worker.log‘, ‘M‘, 5) # 一分钟一个文件,只保留最新的5个 #args=(r‘worker.log‘, ‘D‘, 5) # 一天一个文件,只保留最新的5个
原文:http://my.oschina.net/u/914655/blog/469512