python log日誌 多線程安全

       python中的日誌文件爲logger,常用的有兩個-RotatingFileHandler;TimedRotatingFileHandler。文件沒滿足分割條件前,保存在‘info.log’(自己命名的文件)中,如果滿足分割條件,會生成‘info.log.1’。下一次滿足分割條件後,將‘info.log’保存成‘info.log.1’,而‘info.log.1’順延成‘info.log.2’;滿足最多保存的個數後,會將其刪掉。

       RotatingFileHandler,是按大小劃分日誌文件,使用方法如下。RotatingFileHandler是按文件大小自動分割保存,下文中設置的是1M保存一個文件,最多保存30個。此種方式支持多線程安全,支持軟件的開關機(TimedRotatingFileHandler不支持,一旦關機,會重新計時)

import logging
from logging import handlers

def log_init():
    log = logging.getLogger('error.log')            # log保存位置
    format_str = log.Formatter('%(asctime)s - \     # log時間戳格式
        %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s')                         
    log.setLevel(logging.DEBUG)                     # log日誌等級(往下的內容不保存)
    sh = logging.StreamHandler()                    # 往屏幕上輸出
    # filename:log文件名;maxBytes:超過最大尺寸,log會另存一個文件;
    # backupCount:最多保存多少個日誌;encoding:保存編碼格式
    th = handlers.RotatingFileHandler(filename='error.log', maxBytes=1024*1024, \
                                    backupCount=30, encoding='uft-8')        
    th.setFormatter(format_str)                     # 設置文件裏寫入的格式
    log.addHandler(sh)
    log.addHandler(th)
    return log

if __name__ == '__main__':
    log = log_init()
    log.debug('debug_msg')
    log.info('info_msg')
    log.warning('warning_msg')
    log.error('error_msg')
    log.critical('critical_msg')

        TimedRotatingFileHandler是按日期劃分日誌文件,使用方法如下。TimedRotatingFileHandler是按文件大小自動分割保存,下文中設置的是每天保存一個log文件,最多保存30個。此種方式支持多線程不安全不支持軟件的關機(軟件關機後,會重新計時,如果經常關機的項目,會只記錄在一個文件中)。

import logging
from logging import handlers

def log_init():
    log = logging.getLogger('error.log')            # log保存位置
    format_str = log.Formatter('%(asctime)s - \     # log時間戳格式
        %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s')                         
    log.setLevel(logging.DEBUG)                     # log日誌等級(往下的內容不保存)
    sh = logging.StreamHandler()                    # 往屏幕上輸出
    # filename:log文件名;when:多久另存一個文件(S/M/H/D/W/midnight);
    # backupCount:最多保存多少個日誌;encoding:保存編碼格式
    th = handlers.TimedRotatingFileHandler(filename='error.log', when='D', \
                                    backupCount=30, encoding='uft-8')        
    th.setFormatter(format_str)                     # 設置文件裏寫入的格式
    log.addHandler(sh)
    log.addHandler(th)
    return log

if __name__ == '__main__':
    log = log_init()
    log.debug('debug_msg')
    log.info('info_msg')
    log.warning('warning_msg')
    log.error('error_msg')
    log.critical('critical_msg')

       如果想多線程使用TimedRotatingFileHandler,就需要自己寫一個線程,然後每一個log往消息隊列中丟,用線程處理這個消息隊列。Queue是線程安全的,所以作爲消息隊列使用沒有影響。

import time
import _thread
import logging
from logging import handlers
from queue import Queue

logs_queue = Queue()

class LogMsg(object):
    def __init__(self, type, msg):
        self._type = type
        self._msg = msg

def log_init():
    log = logging.getLogger('error.log')            # log保存位置
    format_str = log.Formatter('%(asctime)s - \     # log時間戳格式
        %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s')                         
    log.setLevel(logging.DEBUG)                     # log日誌等級(往下的內容不保存)
    sh = logging.StreamHandler()                    # 往屏幕上輸出
    # filename:log文件名;when:多久另存一個文件(S/M/H/D/W/midnight);
    # backupCount:最多保存多少個日誌;encoding:保存編碼格式
    th = handlers.TimedRotatingFileHandler(filename='error.log', when='D', \
                                    backupCount=30, encoding='uft-8')        
    th.setFormatter(format_str)                     # 設置文件裏寫入的格式
    log.addHandler(sh)
    log.addHandler(th)
    return log

def cop_log_queue(logger):
    while True:
        if logs_queue.empty():
           time.sleep(1)
        log_msg = logs_queue.get()
        if log_msg._type == 'debug':
            logger.debug(log_msg._msg)
        elif log_msg._type == 'info':
            logger.info(log_msg._msg)
        elif log_msg._type == 'warning':
            logger.warning(log_msg._msg)
        elif log_msg._type == 'error':
            logger.error(log_msg._msg)
        elif log_msg._type == 'critical':
            logger.critical(log_msg._msg)

def error_thread1():
    while True:
        logs_queue.put(LogMsg('debug','debug_msg'))
        time.sleep(1)

def error_thread2():
    while True:
        logs_queue.put(LogMsg('info','info_msg'))
        time.sleep(1)

if __name__ == '__main__':
    logger = log_init()
    _thread.start_new_thread(cope_log_queue, (logger, ))
    _thread.start_new_thread(error_thread1, ())
    _thread.start_new_thread(error_thread2, ())


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章