python作為一門非常容易上手的腳本語言,日志輸出更是簡單,logging模塊,簡單的設(shè)置配置和屬性,就能實現(xiàn)到控制臺輸出日志,在basicConfig()設(shè)置文件名,就能夠?qū)⑷罩拘畔懭胛募?,簡直是簡單到不能再簡單?/p>
最近在項目中就遇到一個日志問題,使用python編寫的服務(wù)程序一直運行,連續(xù)處理一些任務(wù),每個任務(wù)的關(guān)鍵信息都需要輸出到文件中,便于維護人員查看,可是對于簡單實用logging來說,日志寫入文件非常簡單,由于服務(wù)程序連續(xù)運行,一直向一個文件記錄日志信息有些不妥,有常識的開發(fā)人員都知道,長時間的日志輸出會導(dǎo)致日志文件過大,可是如何在服務(wù)運行時,修改日志的輸出文件,以當(dāng)天日期作為日志文件名。
代碼編寫環(huán)境:python3.4.3
首先,想到的是更改logging.basicConfig(filename=logfilename)參數(shù),來實現(xiàn)變更日志文件名的目的。編寫代碼如下:
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')
運行結(jié)果沒有達到預(yù)期的效果,只有日志文件mylog1.txt被創(chuàng)建,mylog2.txt和mylog3.txt都未被創(chuàng)建,連續(xù)3次的輸出的內(nèi)容都寫入mylog1.txt中。說明logging.basicConfig()設(shè)置屬性具有全局性,第一次設(shè)置之后,之后再設(shè)置將不再生效。查看官方文檔,也確實是如此。
logging.basicConfig(**kwargs)
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.
This function does nothing if the root logger already has handlers configured for it.
此路不通,只好用其他方法。
logging支持添加多個不同類型的handler對象,實現(xiàn)對控制臺(logging.StreamHandler)、文件(logging.FileHandler)等不同目標(biāo)輸出日志。
logging支持的日志詳情見文檔logging.handlers
通過增加多個handler對象,可是實現(xiàn)同時在控制臺、文件同時輸出不同級別的日志信息。
# 默認配置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級別或更高的日志信息打印到標(biāo)準(zhǔn)錯誤,并將其添加到當(dāng)前的日志處理對象。 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')
考慮實現(xiàn)簡單又能說明效果,寫入文件使用logging.basicConfig()設(shè)置,并添加輸出指向控制臺的流處理(StreamHandler)對象console,實現(xiàn)同時輸出日志。當(dāng)然也可以反過來,默認設(shè)置控制臺輸出日志,之后創(chuàng)建文件對象(logging.FileHandler),并加入處理集合,實現(xiàn)同樣的效果。
logging.getLogger('')獲取的是名為'root'的默認根節(jié)點
同時,logging提供addHandler()的方法,自然也會有管理handler的方法。
延伸之前Handler的思路,我們可以實現(xiàn)對handler的動態(tài)管理,變更日志文件。每次需要變更輸出文件路徑前,使用handler管理清空原先的logging.FileHandler對象,重新創(chuàng)建一個新文件名的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級別或更高的日志信息打印到標(biāo)準(zhǔn)錯誤,并將其添加到當(dāng)前的日志處理對象。 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循環(huán)執(zhí)行3次處理,分別創(chuàng)建日志文件名稱為mylog1.txt, mylog2.tx, mylog3.txt,并寫入相同的內(nèi)容。執(zhí)行結(jié)果確實產(chǎn)生不同名稱的文件,日志內(nèi)容也正確寫入。
至此,已經(jīng)實現(xiàn)動態(tài)變更輸出文件日志名稱的功能。至于按照日志輸出文件名,只需要按照上述代碼的思路,將創(chuàng)建logging.FileHandler()的文件名參數(shù)變更就能達成目的。
瀏覽官方文檔logging.handlers一節(jié)內(nèi)容,python考慮到日志的常規(guī)使用場景,已經(jīng)封裝更為簡單的實現(xiàn)方案,TimedRotatingFileHandler,只需簡單的配置,即可實現(xiàn)對輸出日志文件的基本管理,靈活易用,代碼如下:
import logging, logging.handlers import time ''' TimedRotatingFileHandler構(gòu)造函數(shù)聲明 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 保留日志最大文件數(shù),超過限制,刪除最先創(chuàng)建的文件;默認值0,表示不限制。 delay 延遲文件創(chuàng)建,直到第一次調(diào)用emit()方法創(chuàng)建日志文件 atTime 在指定的時間(datetime.time格式)創(chuàng)建日志文件。 ''' def test_TimedRotatingFileHandler(): # 定義日志輸出格式 fmt_str = '%(asctime)s[level-%(levelname)s][%(name)s]:%(message)s' # 初始化 logging.basicConfig() # 創(chuàng)建TimedRotatingFileHandler處理對象 # 間隔5(S)創(chuàng)建新的名稱為myLog%Y%m%d_%H%M%S.log的文件,并一直占用myLog文件。 fileshandle = logging.handlers.TimedRotatingFileHandler('myLog', when='S', interval=5, backupCount=3) # 設(shè)置日志文件后綴,以當(dāng)前時間作為日志文件后綴名。 fileshandle.suffix = "%Y%m%d_%H%M%S.log" # 設(shè)置日志輸出級別和格式 fileshandle.setLevel(logging.DEBUG) formatter = logging.Formatter(fmt_str) fileshandle.setFormatter(formatter) # 添加到日志處理對象集合 logging.getLogger('').addHandler(fileshandle) if __name__ == '__main__': test_TimedRotatingFileHandler() # 測試在200s內(nèi)創(chuàng)建文件多個日志文件 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)
補充:使用Python的logging.config.fileConfig配置日志
Python的logging.config.fileConfig方式配置日志,通過解析conf配置文件實現(xiàn)。文件 logglogging.conf 配置如下:
[loggers] keys=root,fileLogger,rotatingFileLogger [handlers] keys=consoleHandler,fileHandler,rotatingFileHandler [formatters] keys=simpleFormatter [logger_root] level=DEBUG handlers=consoleHandler [logger_fileLogger] level=DEBUG # 該logger中配置的handler handlers=fileHandler # logger 的名稱 qualname=fileLogger propagate=0 [logger_rotatingFileLogger] level=DEBUG # 這樣配置,rotatingFileLogger中就同時配置了consoleHandler,rotatingFileHandler # consoleHandler 負責(zé)將日志輸出到控制臺 # rotatingFileHandler 負責(zé)將日志輸出保存到文件中 handlers=consoleHandler,rotatingFileHandler qualname=rotatingFileLogger propagate=0 [handler_consoleHandler] class=StreamHandler level=DEBUG formatter=simpleFormatter args=(sys.stdout,) [handler_fileHandler] class=FileHandler level=DEBUG formatter=simpleFormatter args=('logs/logging.log', 'a') [handler_rotatingFileHandler] class=handlers.RotatingFileHandler level=WARNING formatter=simpleFormatter args=("logs/rotating_logging.log", "a", 1*1024*1024, 5) [formatter_simpleFormatter] #format=%(asctime)s - %(name)s - %(levelname)s - %(message)s format=%(asctime)s - %(module)s - %(thread)d - %(levelname)s : %(message)s datefmt=%Y-%m-%d %H:%M:%S
loggers
: 配置logger信息。必須包含一個名字叫做root的logger,當(dāng)使用無參函數(shù)logging.getLogger()時,默認返回root這個logger,其他自定義logger可以通過 logging.getLogger("fileLogger") 方式進行調(diào)用
handlers
:定義聲明handlers信息。常用的handlers包括 StreamHandler(僅將日志輸出到kong控制臺)、FileHandler(將日志信息輸出保存到文件)、RotaRotatingFileHandler(將日志輸出保存到文件中,并設(shè)置單個日志wenj文件的大小和日志文件個數(shù))
formatter
: 設(shè)置日志格式
logger_xxx
: 對loggers中聲明的logger進行逐個配置,且要一一對應(yīng)
handler_xxx
: 對handlers中聲明的handler進行逐個配置,且要一一對應(yīng)
formatter_xxx
: 對聲明的formatterjinx進行配置
logging.config.fileConfig(“l(fā)ogging.conf”) # 輸出日志到控制臺,獲取的是root對應(yīng)的logger console_logger = logging.getLogger() # 輸出日志到單個文件 file_logger = logging.getLogger(name="fileLogger") # rotatingFileLogger中額consoleHandler輸出到控制臺,rotatingHandler輸出日志到文件 rotating_logger = logging.getLogger(name="rotatingFileLogger")
進行以上配置后,在項目中需要進行日志輸出的地方通過logging.getLogger()方式就可以獲取到du應(yīng)的logger,然后就可以使用logger.info("xxx")jinx進行日志輸出了。
使用這種方式配置日志,一定要在項目的入口函數(shù)中就調(diào)用 logging.config.fileConfig(“l(fā)ogging.conf”)函數(shù),因為 logging.conf 文件中,在handler中配置的是日志文件的相對地址,如果在其他代碼文件中進行調(diào)用,由于相對地址的原因,將導(dǎo)致日志文件會出現(xiàn)在yixi意想不到的位置。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。
標(biāo)簽:內(nèi)江 廊坊 綿陽 黔東 亳州 渭南 拉薩 興安盟
巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《python 實現(xiàn)logging動態(tài)變更輸出日志文件名》,本文關(guān)鍵詞 python,實現(xiàn),logging,動態(tài),變更,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。