本篇文章為大家展示了Python 日志模塊詳解及怎么應(yīng)用,內(nèi)容簡(jiǎn)明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過(guò)這篇文章的詳細(xì)介紹希望你能有所收獲。
發(fā)展壯大離不開(kāi)廣大客戶長(zhǎng)期以來(lái)的信賴(lài)與支持,我們將始終秉承“誠(chéng)信為本、服務(wù)至上”的服務(wù)理念,堅(jiān)持“二合一”的優(yōu)良服務(wù)模式,真誠(chéng)服務(wù)每家企業(yè),認(rèn)真做好每個(gè)細(xì)節(jié),不斷完善自我,成就企業(yè),實(shí)現(xiàn)共贏。行業(yè)涉及成都人造霧等,在網(wǎng)站建設(shè)公司、全網(wǎng)營(yíng)銷(xiāo)推廣、WAP手機(jī)網(wǎng)站、VI設(shè)計(jì)、軟件開(kāi)發(fā)等項(xiàng)目上具有豐富的設(shè)計(jì)經(jīng)驗(yàn)。
日志概述
百度百科的日志概述:
Windows網(wǎng)絡(luò)操作系統(tǒng)都設(shè)計(jì)有各種各樣的日志文件,如應(yīng)用程序日志,安全日志、系統(tǒng)日志、Scheduler服務(wù)日志、FTP日志、WWW日志、DNS服務(wù)器日志等等,這些根據(jù)你的系統(tǒng)開(kāi)啟的服務(wù)的不同而有所不同。我們?cè)谙到y(tǒng)上進(jìn)行一些操作時(shí),這些日志文件通常會(huì)記錄下我們操作的一些相關(guān)內(nèi)容,這些內(nèi)容對(duì)系統(tǒng)安全工作人員相當(dāng)有用。比如說(shuō)有人對(duì)系統(tǒng)進(jìn)行了IPC探測(cè),系統(tǒng)就會(huì)在安全日志里迅速地記下探測(cè)者探測(cè)時(shí)所用的IP、時(shí)間、用戶名等,用FTP探測(cè)后,就會(huì)在FTP日志中記下IP、時(shí)間、探測(cè)所用的用戶名等。
我映像中的日志:
查看日志是開(kāi)發(fā)人員日常獲取信息、排查異常、發(fā)現(xiàn)問(wèn)題的最好途徑,日志記錄中通常會(huì)標(biāo)記有異常產(chǎn)生的原因、發(fā)生時(shí)間、具體錯(cuò)誤行數(shù)等信息,這極大的節(jié)省了我們的排查時(shí)間,無(wú)形中提高了編碼效率。
日志分類(lèi)
我們可以按照輸出終端進(jìn)行分類(lèi),也可以按照日志級(jí)別進(jìn)行分類(lèi)。輸出終端指的是將日志在控制臺(tái)輸出顯示和將日志存入文件;日志級(jí)別指的是 Debug、Info、WARNING、ERROR以及CRITICAL等嚴(yán)重等級(jí)進(jìn)行劃分。
Python 的 logging
logging提供了一組便利的日志函數(shù),它們分別是:debug()、 info()、 warning()、 error() 和 critical()。logging函數(shù)根據(jù)它們用來(lái)跟蹤的事件的級(jí)別或嚴(yán)重程度來(lái)命名。標(biāo)準(zhǔn)級(jí)別及其適用性描述如下(以嚴(yán)重程度遞增排序):
每個(gè)級(jí)別對(duì)應(yīng)的數(shù)字值為
CRITICAL:50,ERROR:40,WARNING:30,INFO:20,DEBUG:10,NOTSET:0。
Python 中日志的默認(rèn)等級(jí)是 WARNING,DEBUG 和 INFO 級(jí)別的日志將不會(huì)得到顯示,在 logging 中更改設(shè)置。
使用 logging 在控制臺(tái)打印日志,這里我們用 Pycharm 編輯器來(lái)觀察:
import logging
logging.debug('崔慶才丨靜覓、韋世東丨奎因')
logging.warning('邀請(qǐng)你關(guān)注微信公眾號(hào)【進(jìn)擊的 Coder】')
logging.info('和大佬一起coding、共同進(jìn)步')
有什么辦法可以改變默認(rèn)的日志級(jí)別呢?
當(dāng)然是有的,logging 中提供了 basicConfig 讓使用者可以適時(shí)調(diào)節(jié)默認(rèn)日志級(jí)別,我們可以將上面的代碼改為:
import logging
logging.basicConfig(level=logging.DEBUG)
logging.debug('崔慶才丨靜覓、韋世東丨奎因')
logging.warning('邀請(qǐng)你關(guān)注微信公眾號(hào)【進(jìn)擊的 Coder】')
logging.info('和大佬一起coding、共同進(jìn)步')
在 basicConfig 中設(shè)定 level 參數(shù)的級(jí)別即可。
思考:如果設(shè)定級(jí)別為 logging.INFO,那 DEBUG 信息能夠顯示么?
剛才演示了如何在控制臺(tái)輸出日志內(nèi)容,并且自由設(shè)定日志的級(jí)別,那現(xiàn)在就來(lái)看看如何將日志保存到文件。依舊是強(qiáng)大的 basicConfig,我們?cè)賹⑸厦娴拇a改為:
import logging
logging.basicConfig(level=logging.DEBUG, filename='coder.log', filemode='a')
logging.debug('崔慶才丨靜覓、韋世東丨奎因')
logging.warning('邀請(qǐng)你關(guān)注微信公眾號(hào)【進(jìn)擊的 Coder】')
logging.info('和大佬一起coding、共同進(jìn)步')
通過(guò)簡(jiǎn)單的代碼設(shè)置,我們就完成了日志文件在控制臺(tái)和文件中的輸出。那既在控制臺(tái)顯示又能保存到文件中呢?
logging所提供的模塊級(jí)別的日志記錄函數(shù)是對(duì)logging日志系統(tǒng)相關(guān)類(lèi)的封裝
logging 模塊提供了兩種記錄日志的方式:
使用logging提供的模塊級(jí)別的函數(shù)
使用Logging日志系統(tǒng)的四大組件
這里提到的級(jí)別函數(shù)就是上面所用的 DEBGE、ERROR 等級(jí)別,而四大組件則是指 loggers、handlers、filters 和 formatters 這幾個(gè)組件,下圖簡(jiǎn)單明了的闡述了它們各自的作用:
下面介紹下與logging四大組件相關(guān)的類(lèi):Logger, Handler, Filter, Formatter。
Logger類(lèi)
Logger 對(duì)象有3個(gè)工作要做:
1)向應(yīng)用程序代碼暴露幾個(gè)方法,使應(yīng)用程序可以在運(yùn)行時(shí)記錄日志消息;
2)基于日志嚴(yán)重等級(jí)(默認(rèn)的過(guò)濾設(shè)施)或filter對(duì)象來(lái)決定要對(duì)哪些日志進(jìn)行后續(xù)處理;
3)將日志消息傳送給所有感興趣的日志handlers。
Logger對(duì)象最常用的方法分為兩類(lèi):配置方法 和 消息發(fā)送方法
最常用的配置方法如下:
關(guān)于Logger.setLevel()方法的說(shuō)明:
內(nèi)建等級(jí)中,級(jí)別最低的是DEBUG,級(jí)別最高的是CRITICAL。例如setLevel(logging.INFO),此時(shí)函數(shù)參數(shù)為INFO,那么該logger將只會(huì)處理INFO、WARNING、ERROR和CRITICAL級(jí)別的日志,而DEBUG級(jí)別的消息將會(huì)被忽略/丟棄。
logger對(duì)象配置完成后,可以使用下面的方法來(lái)創(chuàng)建日志記錄:
logging.getLogger()方法有一個(gè)可選參數(shù)name,該參數(shù)表示將要返回的日志器的名稱(chēng)標(biāo)識(shí),如果不提供該參數(shù),則其值為'root'。若以相同的name參數(shù)值多次調(diào)用getLogger()方法,將會(huì)返回指向同一個(gè)logger對(duì)象的引用。
關(guān)于logger的層級(jí)結(jié)構(gòu)與有效等級(jí)的說(shuō)明:
logger的名稱(chēng)是一個(gè)以'.'分割的層級(jí)結(jié)構(gòu),每個(gè)'.'后面的logger都是'.'前面的logger的children,例如,有一個(gè)名稱(chēng)為 foo 的logger,其它名稱(chēng)分別為 foo.bar, foo.bar.baz 和 foo.bam都是 foo 的后代。
logger有一個(gè)"有效等級(jí)(effective level)"的概念。如果一個(gè)logger上沒(méi)有被明確設(shè)置一個(gè)level,那么該logger就是使用它parent的level;如果它的parent也沒(méi)有明確設(shè)置level則繼續(xù)向上查找parent的parent的有效level,依次類(lèi)推,直到找到個(gè)一個(gè)明確設(shè)置了level的祖先為止。需要說(shuō)明的是,root logger總是會(huì)有一個(gè)明確的level設(shè)置(默認(rèn)為 WARNING)。當(dāng)決定是否去處理一個(gè)已發(fā)生的事件時(shí),logger的有效等級(jí)將會(huì)被用來(lái)決定是否將該事件傳遞給該logger的handlers進(jìn)行處理。
child loggers在完成對(duì)日志消息的處理后,默認(rèn)會(huì)將日志消息傳遞給與它們的祖先loggers相關(guān)的handlers。因此,我們不必為一個(gè)應(yīng)用程序中所使用的所有l(wèi)oggers定義和配置handlers,只需要為一個(gè)頂層的logger配置handlers,然后按照需要?jiǎng)?chuàng)建child loggers就可足夠了。我們也可以通過(guò)將一個(gè)logger的propagate屬性設(shè)置為False來(lái)關(guān)閉這種傳遞機(jī)制。
Handler
Handler對(duì)象的作用是(基于日志消息的level)將消息分發(fā)到handler指定的位置(文件、網(wǎng)絡(luò)、郵件等)。Logger對(duì)象可以通過(guò)addHandler()方法為自己添加0個(gè)或者更多個(gè)handler對(duì)象。比如,一個(gè)應(yīng)用程序可能想要實(shí)現(xiàn)以下幾個(gè)日志需求:
1)把所有日志都發(fā)送到一個(gè)日志文件中;
2)把所有嚴(yán)重級(jí)別大于等于error的日志發(fā)送到stdout(標(biāo)準(zhǔn)輸出);
3)把所有嚴(yán)重級(jí)別為critical的日志發(fā)送到一個(gè)email郵件地址。
這種場(chǎng)景就需要3個(gè)不同的handlers,每個(gè)handler復(fù)雜發(fā)送一個(gè)特定嚴(yán)重級(jí)別的日志到一個(gè)特定的位置。
一個(gè)handler中只有非常少數(shù)的方法是需要應(yīng)用開(kāi)發(fā)人員去關(guān)心的。對(duì)于使用內(nèi)建handler對(duì)象的應(yīng)用開(kāi)發(fā)人員來(lái)說(shuō),似乎唯一相關(guān)的handler方法就是下面這幾個(gè)配置方法:
Formater
Formater對(duì)象用于配置日志信息的最終順序、結(jié)構(gòu)和內(nèi)容。與logging.Handler基類(lèi)不同的是,應(yīng)用代碼可以直接實(shí)例化Formatter類(lèi)。另外,如果你的應(yīng)用程序需要一些特殊的處理行為,也可以實(shí)現(xiàn)一個(gè)Formatter的子類(lèi)來(lái)完成。
Formatter類(lèi)的構(gòu)造方法定義如下:
logging.Formatter.__init__(fmt=None, datefmt=None, style='%')
該構(gòu)造方法接收3個(gè)可選參數(shù):
fmt:指定消息格式化字符串,如果不指定該參數(shù)則默認(rèn)使用message的原始值
datefmt:指定日期格式字符串,如果不指定該參數(shù)則默認(rèn)使用"%Y-%m-%d %H:%M:%S"
style:Python 3.2新增的參數(shù),可取值為 '%', '{'和 '$',如果不指定該參數(shù)則默認(rèn)使用'%'
Filter
Filter可以被Handler和Logger用來(lái)做比level更細(xì)粒度的、更復(fù)雜的過(guò)濾功能。Filter是一個(gè)過(guò)濾器基類(lèi),它只允許某個(gè)logger層級(jí)下的日志事件通過(guò)過(guò)濾。該類(lèi)定義如下:
class logging.Filter(name='')
filter(record)
比如,一個(gè)filter實(shí)例化時(shí)傳遞的name參數(shù)值為'A.B',那么該filter實(shí)例將只允許名稱(chēng)為類(lèi)似如下規(guī)則的loggers產(chǎn)生的日志記錄通過(guò)過(guò)濾:'A.B','A.B,C','A.B.C.D','A.B.D',而名稱(chēng)為'A.BB', 'B.A.B'的loggers產(chǎn)生的日志則會(huì)被過(guò)濾掉。如果name的值為空字符串,則允許所有的日志事件通過(guò)過(guò)濾。
filter方法用于具體控制傳遞的record記錄是否能通過(guò)過(guò)濾,如果該方法返回值為0表示不能通過(guò)過(guò)濾,返回值為非0表示可以通過(guò)過(guò)濾。
說(shuō)明:
如果有需要,也可以在filter(record)方法內(nèi)部改變?cè)搑ecord,比如添加、刪除或修改一些屬性。
我們還可以通過(guò)filter做一些統(tǒng)計(jì)工作,比如可以計(jì)算下被一個(gè)特殊的logger或handler所處理的record數(shù)量等。
上面文縐縐的說(shuō)了(復(fù)制/粘貼)那么多,現(xiàn)在應(yīng)該動(dòng)手實(shí)踐了。
現(xiàn)在我需要既將日志輸出到控制臺(tái)、又能將日志保存到文件,我應(yīng)該怎么辦?
利用剛才所學(xué)的知識(shí),我們可以構(gòu)思一下:
看起來(lái)好像也不難,挺簡(jiǎn)單的樣子,但是實(shí)際如此嗎?
在實(shí)際的工作或應(yīng)用中,我們或許還需要指定文件存放路徑、用隨機(jī)數(shù)作為日志文件名、顯示具體的信息輸出代碼行數(shù)、日志信息輸出日期和日志寫(xiě)入方式等內(nèi)容。再構(gòu)思一下:
import os
import logging
import uuid
from logging import Handler, FileHandler, StreamHandler
class PathFileHandler(FileHandler):
def __init__(self, path, filename, mode='a', encoding=None, delay=False):
filename = os.fspath(filename)
if not os.path.exists(path):
os.mkdir(path)
self.baseFilename = os.path.join(path, filename)
self.mode = mode
self.encoding = encoding
self.delay = delay
if delay:
Handler.__init__(self)
self.stream = None
else:
StreamHandler.__init__(self, self._open())
class Loggers(object):
# 日志級(jí)別關(guān)系映射
level_relations = {
'debug': logging.DEBUG, 'info': logging.INFO, 'warning': logging.WARNING,
'error': logging.ERROR, 'critical': logging.CRITICAL
}
def __init__(self, filename='{uid}.log'.format(uid=uuid.uuid4()), level='info', log_dir='log',
fmt='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s'):
self.logger = logging.getLogger(filename)
abspath = os.path.dirname(os.path.abspath(__file__))
self.directory = os.path.join(abspath, log_dir)
format_str = logging.Formatter(fmt) # 設(shè)置日志格式
self.logger.setLevel(self.level_relations.get(level)) # 設(shè)置日志級(jí)別
stream_handler = logging.StreamHandler() # 往屏幕上輸出
stream_handler.setFormatter(format_str)
file_handler = PathFileHandler(path=self.directory, filename=filename, mode='a')
file_handler.setFormatter(format_str)
self.logger.addHandler(stream_handler)
self.logger.addHandler(file_handler)
if __name__ == "__main__":
txt = "關(guān)注公眾號(hào)【進(jìn)擊的 Coder】,回復(fù)『日志代碼』可以領(lǐng)取文章中完整的代碼以及流程圖"
log = Loggers(level='debug')
log.logger.info(4)
log.logger.info(5)
log.logger.info(txt)
文件保存后運(yùn)行,運(yùn)行結(jié)果如下圖所示:
日志確實(shí)在控制臺(tái)輸出了,再來(lái)看一下目錄內(nèi)是否生成有指定的文件和文件夾:
文件打開(kāi)后可以看到里面輸出的內(nèi)容:
上述內(nèi)容就是Python 日志模塊詳解及怎么應(yīng)用,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
分享題目:Python日志模塊詳解及怎么應(yīng)用
網(wǎng)站路徑:http://www.rwnh.cn/article24/peohce.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供虛擬主機(jī)、網(wǎng)站排名、網(wǎng)站建設(shè)、建站公司、定制網(wǎng)站、搜索引擎優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
網(wǎng)頁(yè)設(shè)計(jì)公司知識(shí)