Python

python 多线程中 日志按天分割

2018-12-29  本文已影响240人  cooooper

python 的 logging 模块, 在多线程应用中, logging.hanlders.TimedRotatingFileHandler 不能正常按日期分割。

解决办法为:重写FileHandler类,用于多线程中日志按天分割。

# 重写FileHandler类,用于多线程中日志按天分割
class SafeFileHandler(logging.FileHandler):
    def __init__(self, filename, mode, encoding=None, delay=0):
        """
        Use the specified filename for streamed logging
        """
        encoding = None
        logging.FileHandler.__init__(self, filename, mode='a', encoding=None, delay=False)
        self.mode = mode
        self.encoding = encoding
        self.suffix = "%Y-%m-%d"
        self.suffix_time = ""

    def emit(self, record):
        """
        Emit a record.

        Always check time 
        """
        try:
            if self.check_baseFilename(record):
                self.build_baseFilename()
            logging.FileHandler.emit(self, record)
        except (KeyboardInterrupt, SystemExit):
            raise
        except:
            self.handleError(record)
            
    def check_baseFilename(self, record):
        """
        Determine if builder should occur.
        
        record is not used, as we are just comparing times, 
        but it is needed so the method signatures are the same
        """
        timeTuple = time.localtime()
        
        if self.suffix_time != time.strftime(self.suffix, timeTuple) or not os.path.exists(self.baseFilename+'.'+self.suffix_time):
            return 1
        else:
            return 0
    def build_baseFilename(self):
        """
        do builder; in this case, 
        old time stamp is removed from filename and
        a new time stamp is append to the filename
        """
        if self.stream:
            self.stream.close()
            self.stream = None
        
        # remove old suffix
        if self.suffix_time != "":
            index = self.baseFilename.find("."+self.suffix_time)
            if index == -1:
                index = self.baseFilename.rfind(".")
            self.baseFilename = self.baseFilename[:index]
        
        # add new suffix
        currentTimeTuple = time.localtime()
        self.suffix_time = time.strftime(self.suffix, currentTimeTuple)
        self.baseFilename  = self.baseFilename + "." + self.suffix_time
        
        self.mode = 'a'
        if not self.delay:
            self.stream = self._open()

之后,Logger定义日志的各种参数(格式等):

class Logger(object):
    # 日志级别关系映射
    level_relations = {
        'debug':logging.DEBUG,
        'info':logging.INFO,
        'warning':logging.WARNING,
        'error':logging.ERROR,
        'critical':logging.CRITICAL
    }

    def __init__(self, filename, level='info', when='D', backCount=7,
                 fmt= '%(asctime)s  -  %(pathname)s  [line:%(lineno)d]  -  %(levelname)s:  %(message)s'):
        self.logger = logging.getLogger('mylogger')
        # 创建日志目录(路径logdir可从自定义配置文件导入,或实例化时传入)
        self.mkdir(logdir)
        # 设置日志格式
        format_str = logging.Formatter(fmt)
        self.logger.setLevel(self.level_relations.get(level))#设置日志级别
        # 指定间隔时间自动生成文件的处理器(用于debug)
        th = SafeFileHandler(filename=filename, mode='a')
        # 设置文件里写入的格式
        th.setFormatter(format_str)
        # 把对象加到logger里
        self.logger.addHandler(th)

    def mkdir(self, path) -> None:
        # 如果不存在则创建目录
        if not os.path.exists(path):
            os.makedirs(path)

实例化日志:

mylogger = Logger(filename='all.log', level='debug')
上一篇下一篇

猜你喜欢

热点阅读