消息與記錄
剛才談到了關(guān)于歷史賬號(hào)的文章與消息記錄,所以今天想跟大家聊聊Python關(guān)于消息記錄的模塊:日志管理模塊?logging。
學(xué)習(xí)python的第一課,肯定都是
print('Hello Wrold...')
。但print僅僅使用于我們?nèi)粘W(xué)習(xí),當(dāng)我們的程序需要部署上線(xiàn)時(shí),程序必須要具備記錄日志與程序輸出的功能。此時(shí)print就不能滿(mǎn)足我們的需求,而logging應(yīng)運(yùn)而生。
logging是python的內(nèi)置模塊,無(wú)需安裝即可直接使用。logging模塊借鑒了Apache的Log4j中很多的功能與特性,使用起來(lái)較為方便,不論你是最簡(jiǎn)單無(wú)腦輸出還是定義自己的過(guò)濾器與格式,最終都能滿(mǎn)足大家的需求,所以logging模塊是你的必修課!
Logging入門(mén)
日志級(jí)別
不論是python、java還是C,日志的級(jí)別都是統(tǒng)一規(guī)定的:
日志級(jí)別 | 使用范圍 |
---|---|
FATAL | 致命錯(cuò)誤 |
CRITICAL | 嚴(yán)重的錯(cuò)誤,如內(nèi)存耗盡、磁盤(pán)空間不足等. |
ERROR | 錯(cuò)誤,如IO異常,文件讀寫(xiě)異常等 |
WARNING | 警告類(lèi)錯(cuò)誤,如用戶(hù)輸入密碼即將過(guò)期提醒等 |
INFO | 處理請(qǐng)求或者用戶(hù)操作的狀態(tài)及日常事務(wù)日志 |
DEBUG | 調(diào)試過(guò)程中使用的日志等級(jí),可用于后臺(tái)問(wèn)題定位 |
那么logging中存在哪些?默認(rèn)分為六種日志級(jí)別(括號(hào)為級(jí)別對(duì)應(yīng)的數(shù)值),NOTSET(0)、DEBUG(10)、INFO(20)、WARNING(30)、ERROR(40)、CRITICAL(50)。
簡(jiǎn)單日志打印
說(shuō)了半天的日志級(jí)別,那么這東西對(duì)日志記錄有什么用?此時(shí)我們需要了解LogLevel。logging模塊默認(rèn)記錄日志的級(jí)別是大于等于WARNING。那么讓我們來(lái)看第一個(gè)例子:
理想中我們期望的打印結(jié)果是從debug到critical,但現(xiàn)實(shí)是日志從warning級(jí)別開(kāi)始打印。而且這種日志的打印和print又有什么區(qū)別,我們需要豐滿(mǎn)日志的內(nèi)容,提升逼格。
配置日志輸出
logging提供了basicConfig函數(shù),用于對(duì)日志輸入進(jìn)行相關(guān)配置。
讓我們來(lái)看看basicConfig有哪些可配置參數(shù)吧:
filename: 指定日志文件名
filemode: 和file函數(shù)意義相同,指定日志文件的打開(kāi)模式,’w’或’a’
format: 指定輸出的格式和內(nèi)容,format可以輸出很多有用信息,如上例所示:
%(levelno)s: 打印日志級(jí)別的數(shù)值
%(levelname)s: 打印日志級(jí)別名稱(chēng)
%(pathname)s: 打印當(dāng)前執(zhí)行程序的路徑,其實(shí)就是sys.argv[0]
%(filename)s: 打印當(dāng)前執(zhí)行程序名
%(funcName)s: 打印日志的當(dāng)前函數(shù)
%(lineno)d: 打印日志的當(dāng)前行號(hào)
%(asctime)s: 打印日志的時(shí)間
%(thread)d: 打印線(xiàn)程ID
%(threadName)s: 打印線(xiàn)程名稱(chēng)
%(process)d: 打印進(jìn)程ID
%(message)s: 打印日志信息
datefmt: 指定時(shí)間格式,同time.strftime()
level: 設(shè)置日志級(jí)別,默認(rèn)為logging.WARNING
stream: 指定將日志的輸出流,可以指定輸出到sys.stderr,sys.stdout或者文件,
????默認(rèn)輸出到sys.stderr,當(dāng)stream和filename同時(shí)指定時(shí),stream被忽略
通過(guò)配置basicConfig,日志輸出看起來(lái)就工整多了…當(dāng)看到第一個(gè)filename的時(shí)候就想到了,現(xiàn)在的日志都是在控制臺(tái)輸出的,我們添加該參數(shù)后,就可以將日志輸出到文本了,對(duì)吧?答案是肯定的,如下圖:
但此時(shí)出現(xiàn)一個(gè)問(wèn)題,我們的日志都保存到了文本中,前臺(tái)的控制欄不再具備日志輸出功能了!
Logging進(jìn)階
剛才提到的入門(mén)使用,只是針對(duì)logging的一個(gè)簡(jiǎn)單操作,如果我們想深入的去使用logging模塊,就必須了解Logger,Handler,F(xiàn)ormatter,F(xiàn)ilter的概念:
-
Logger提供了應(yīng)用程序可以直接使用的接口;
-
Handler將(logger創(chuàng)建的)日志記錄發(fā)送到合適的目的輸出;
-
Filters提供了細(xì)度設(shè)備來(lái)決定輸出哪條日志記錄;
-
Formatter決定日志記錄的最終輸出格式。
Logger
Logger 對(duì)象要做三件事情。首先,它們向應(yīng)用代碼暴露了許多方法,這樣應(yīng)用可以在運(yùn)行時(shí)記錄消息。其次,記錄器對(duì)象通過(guò)嚴(yán)重程度(默認(rèn)的過(guò)濾設(shè)施)或者過(guò)濾器對(duì)象來(lái)決定哪些日志消息需要記錄下來(lái)。第三,記錄器對(duì)象將相關(guān)的日志消息傳遞給所有感興趣的日志處理器。
常用的記錄器對(duì)象的方法分為兩類(lèi):配置和發(fā)送消息。
這些是最常用的配置方法:
Logger.setLevel()指定logger將會(huì)處理的最低的安全等級(jí)日志信息, debug是最低的內(nèi)置安全等級(jí),critical是最高的內(nèi)建安全等級(jí)。例如,如果嚴(yán)重程度為INFO,記錄器將只處理INFO,WARNING,ERROR和CRITICAL消息,DEBUG消息被忽略。
Logger.addHandler()和Logger.removeHandler()從記錄器對(duì)象中添加和刪除處理程序?qū)ο蟆L幚砥髟斠?jiàn)Handlers。
Logger.addFilter()和Logger.removeFilter()從記錄器對(duì)象添加和刪除過(guò)濾器對(duì)象。
Handlers
處理程序?qū)ο筘?fù)責(zé)將適當(dāng)?shù)娜罩鞠ⅲɑ谌罩鞠⒌膰?yán)重性)分派到處理程序的指定目標(biāo)。Logger 對(duì)象可以通過(guò)addHandler()方法增加零個(gè)或多個(gè)handler對(duì)象。舉個(gè)例子,一個(gè)應(yīng)用可以將所有的日志消息發(fā)送至日志文件,所有的錯(cuò)誤級(jí)別(error)及以上的日志消息發(fā)送至標(biāo)準(zhǔn)輸出,所有的嚴(yán)重級(jí)別(critical)日志消息發(fā)送至某個(gè)電子郵箱。在這個(gè)例子中需要三個(gè)獨(dú)立的處理器,每一個(gè)負(fù)責(zé)將特定級(jí)別的消息發(fā)送至特定的位置。
其中常用的有4種:
-
logging.StreamHandler -> 控制臺(tái)輸出
-
logging.FileHandler -> 文件輸出
-
logging.handlers.RotatingFileHandler
-
logging.handlers.TimedRotatingFileHandler
Formatter
Formatter對(duì)象設(shè)置日志信息最后的規(guī)則、結(jié)構(gòu)和內(nèi)容,默認(rèn)的時(shí)間格式為%Y-%m-%d %H:%M:%S,下面是Formatter常用的一些信息
參數(shù) | 說(shuō)明 |
---|---|
%(name)s | Logger的名字 |
%(levelno)s | 數(shù)字形式的日志級(jí)別 |
%(levelname)s | 文本形式的日志級(jí)別 |
%(pathname)s | 調(diào)用日志輸出函數(shù)的模塊的完整路徑名,可能沒(méi)有 |
%(filename)s | 調(diào)用日志輸出函數(shù)的模塊的文件名 |
%(module)s | 調(diào)用日志輸出函數(shù)的模塊名 |
%(funcName)s | 調(diào)用日志輸出函數(shù)的函數(shù)名 |
%(lineno)d | 調(diào)用日志輸出函數(shù)的語(yǔ)句所在的代碼行 |
%(created)f | 當(dāng)前時(shí)間,用UNIX標(biāo)準(zhǔn)的表示時(shí)間的浮 點(diǎn)數(shù)表示 |
%(relativeCreated)d | 輸出日志信息時(shí)的,自Logger創(chuàng)建以 來(lái)的毫秒數(shù) |
%(asctime)s | 字符串形式的當(dāng)前時(shí)間。默認(rèn)格式是 “2003-07-08 16:49:45,896”。逗號(hào)后面的是毫秒 |
%(thread)d | 線(xiàn)程ID。可能沒(méi)有 |
%(threadName)s | 線(xiàn)程名。可能沒(méi)有 |
%(process)d | 進(jìn)程ID。可能沒(méi)有 |
%(message)s | 用戶(hù)輸出的消息 |
此時(shí)我們就可以實(shí)現(xiàn)日志的前后臺(tái)輸出了:
此時(shí),前后臺(tái)均輸出了相關(guān)的日志信息。
Logging特別操作
日志切片
有時(shí)候,系統(tǒng)后臺(tái)的日志會(huì)輸出的比較頻繁,那么我們?nèi)绾螌⑷罩景凑沾笮』蛘邥r(shí)間進(jìn)行切片呢?這里就要用到剛才介紹的:
-
logging.handlers.RotatingFileHandler
-
logging.handlers.TimedRotatingFileHandler
每隔 1000 Byte 劃分一個(gè)日志文件,備份文件為 3 個(gè)
file_handler = logging.handlers.RotatingFileHandler("test.log", mode="w", maxBytes=1000, backupCount=3, encoding="utf-8")
每隔 1小時(shí) 劃分一個(gè)日志文件,interval 是時(shí)間間隔,備份文件為 10 個(gè)
handler2 = logging.handlers.TimedRotatingFileHandler("test.log", when="H", interval=1, backupCount=10)
我們以RotatingFileHandler為例,為了演示方便,我設(shè)置文件大小為3kb:
最終實(shí)現(xiàn):
關(guān)于異常日志
logging模塊在對(duì)異常獲取時(shí),進(jìn)行了相關(guān)的優(yōu)化操作,來(lái)看下這個(gè)例子:
由此可見(jiàn),當(dāng)我們?cè)趯?duì)異常結(jié)果進(jìn)行日志輸出時(shí),最好使用logger.exception。
其實(shí)logging模塊的內(nèi)容還有很多,比如封裝與繼承,今天就先介紹到這里,有空了繼續(xù)為大家補(bǔ)充。
The End
OK,今天的內(nèi)容就到這里,如果覺(jué)得內(nèi)容對(duì)你有所幫助,歡迎點(diǎn)贊。
期待你關(guān)注我的公眾號(hào)
清風(fēng)Python
,如果覺(jué)得不錯(cuò),希望能動(dòng)動(dòng)手指轉(zhuǎn)發(fā)給你身邊的朋友們。
作者:清風(fēng)Python
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
