首页 > 编程语言 > 详细

python logging 多进程写兼容模块

时间:2015-06-22 23:31:55      阅读:1672      评论:0      收藏:0      [点我收藏+]

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个


python logging 多进程写兼容模块

原文:http://my.oschina.net/u/914655/blog/469512

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!