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, ())