python做爲一門很是容易上手的腳本語言,日誌輸出更是簡單,logging模塊,簡單的設置配置和屬性,就能實現到控制檯輸出日誌,在basicConfig()設置文件名,就可以將日誌信息寫入文件,簡直是簡單到不能再簡單。
最近在項目中就遇到一個日誌問題,使用python編寫的服務程序一直運行,連續處理一些任務,每一個任務的關鍵信息都須要輸出到文件中,便於維護人員查看,但是對於簡單實用logging來講,日誌寫入文件很是簡單,因爲服務程序連續運行,一直向一個文件記錄日誌信息有些不妥,有常識的開發人員都知道,長時間的日誌輸出會致使日誌文件過大,但是如何在服務運行時,修改日誌的輸出文件,以當天日期做爲日誌文件名。python
代碼編寫環境:python3.4.3app
首先,想到的是更改logging.basicConfig(filename=logfilename)參數,來實現變動日誌文件名的目的。編寫代碼以下:函數
log_fmt = '%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s' for i in range(1,4): filename = str.format('mylog%d.txt' % i) logging.basicConfig(format=log_fmt, level=logging.DEBUG, filename=filename) logging.debug('This is debug message') logging.info('This is info message') logging.warning('This is warning message')
運行結果沒有達到預期的效果,只有日誌文件mylog1.txt被建立,mylog2.txt和mylog3.txt都未被建立,連續3次的輸出的內容都寫入mylog1.txt中。說明logging.basicConfig()設置屬性具備全局性,第一次設置以後,以後再設置將再也不生效。查看官方文檔,也確實是如此。測試
logging.basicConfig(**kwargs)spa
Does basic configuration for the logging system by creating a StreamHandler with a default Formatter and adding it to the root logger. The functions debug(), info(), warning(), error() and critical() will call basicConfig() automatically if no handlers are defined for the root logger.debug
This function does nothing if the root logger already has handlers configured for it.日誌
此路不通,只好用其餘方法。code
logging支持添加多個不一樣類型的handler對象,實現對控制檯(logging.StreamHandler)、文件(logging.FileHandler)等不一樣目標輸出日誌。orm
logging支持的日誌詳情見文檔
logging.handlers
對象
經過增長多個handler對象,但是實現同時在控制檯、文件同時輸出不一樣級別的日誌信息。
# 默認配置logging寫入本地文件 logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%a, %d %b %Y %H:%M:%S', filename='myapp2.log', filemode='w') #定義一個StreamHandler,將INFO級別或更高的日誌信息打印到標準錯誤,並將其添加到當前的日誌處理對象。 console = logging.StreamHandler() console.setLevel(logging.INFO) formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') console.setFormatter(formatter) logging.getLogger('').addHandler(console) logging.debug('This is debug message') logging.info('This is info message') logging.warning('This is warning message')
考慮實現簡單又能說明效果,寫入文件使用logging.basicConfig()設置,並添加輸出指向控制檯的流處理(StreamHandler)對象console,實現同時輸出日誌。固然也能夠反過來,默認設置控制檯輸出日誌,以後建立文件對象(logging.FileHandler),並加入處理集合,實現一樣的效果。
logging.getLogger('')
獲取的是名爲’root’的默認根節點
同時,logging提供addHandler()的方法,天然也會有管理handler的方法。
延伸以前Handler的思路,咱們能夠實現對handler的動態管理,變動日誌文件。每次須要變動輸出文件路徑前,使用handler管理清空原先的logging.FileHandler對象,從新建立一個新文件名的logging.FileHandler對象便可。
# 默認配置logging寫入本地文件 logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%a, %d %b %Y %H:%M:%S', filename='myapp2.log', filemode='w') #定義一個StreamHandler,將INFO級別或更高的日誌信息打印到標準錯誤,並將其添加到當前的日誌處理對象。 console = logging.StreamHandler() console.setLevel(logging.INFO) formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') console.setFormatter(formatter) logging.getLogger('').addHandler(console) logging.debug('This is debug message') logging.info('This is info message') logging.warning('This is warning message')
使用for循環執行3次處理,分別建立日誌文件名稱爲mylog1.txt, mylog2.tx, mylog3.txt,並寫入相同的內容。執行結果確實產生不一樣名稱的文件,日誌內容也正確寫入。
至此,已經實現動態變動輸出文件日誌名稱的功能。至於按照日誌輸出文件名,只須要按照上述代碼的思路,將建立logging.FileHandler()的文件名參數變動就能達成目的。
瀏覽官方文檔logging.handlers一節內容,python考慮到日誌的常規使用場景,已經封裝更爲簡單的實現方案,TimedRotatingFileHandler,只需簡單的配置,便可實現對輸出日誌文件的基本管理,靈活易用,代碼以下:
import logging, logging.handlers import time ''' TimedRotatingFileHandler構造函數聲明 class logging.handlers.TimedRotatingFileHandler(filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False, atTime=None) filename 日誌文件名前綴 when 日誌名變動時間單位 'S' Seconds 'M' Minutes 'H' Hours 'D' Days 'W0'-'W6' Weekday (0=Monday) 'midnight' Roll over at midnight interval 間隔時間,是指等待N個when單位的時間後,自動重建文件 backupCount 保留日誌最大文件數,超過限制,刪除最早建立的文件;默認值0,表示不限制。 delay 延遲文件建立,直到第一次調用emit()方法建立日誌文件 atTime 在指定的時間(datetime.time格式)建立日誌文件。 ''' def test_TimedRotatingFileHandler(): # 定義日誌輸出格式 fmt_str = '%(asctime)s[level-%(levelname)s][%(name)s]:%(message)s' # 初始化 logging.basicConfig() # 建立TimedRotatingFileHandler處理對象 # 間隔5(S)建立新的名稱爲myLog%Y%m%d_%H%M%S.log的文件,並一直佔用myLog文件。 fileshandle = logging.handlers.TimedRotatingFileHandler('myLog', when='S', interval=5, backupCount=3) # 設置日誌文件後綴,以當前時間做爲日誌文件後綴名。 fileshandle.suffix = "%Y%m%d_%H%M%S.log" # 設置日誌輸出級別和格式 fileshandle.setLevel(logging.DEBUG) formatter = logging.Formatter(fmt_str) fileshandle.setFormatter(formatter) # 添加到日誌處理對象集合 logging.getLogger('').addHandler(fileshandle) if __name__ == '__main__': test_TimedRotatingFileHandler() # 測試在200s內建立文件多個日誌文件 for i in range(0, 100): logging.debug("logging.debug") logging.info("logging.info") logging.warning("logging.warning") logging.error("logging.error") time.sleep(2)