在以往我們使用日志,更多的是使用 python 自帶的 logging 模塊,它可以設(shè)置錯(cuò)誤等級(jí)、輸出方式等。
成都創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供武夷山網(wǎng)站建設(shè)、武夷山做網(wǎng)站、武夷山網(wǎng)站設(shè)計(jì)、武夷山網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)與制作、武夷山企業(yè)網(wǎng)站模板建站服務(wù),10余年武夷山做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。
但使用方式相對(duì)比較復(fù)雜,想要更好的使用需要如 log4net 一樣單獨(dú)配置,這在 python 中感覺(jué)不是很優(yōu)雅。
下面介紹一個(gè) python 庫(kù): loguru 。 guru 是印度語(yǔ)中大師的意思, loguru 直譯就是“日志大師”。
如圖 logging 一樣, loguru 也有定義日志等級(jí)。不同的日志等級(jí),輸出效果也不一樣(默認(rèn)的等級(jí)由低到高是 DEBUG 、 INFO 、 WARNING 、 ERROR 、 CRITICAL ,也可以自己使用 level 函數(shù)定義)。
類似 logging 中的 logger.addHandler ,loguru統(tǒng)一使用 add 函數(shù)來(lái)管理格式、文件輸出、過(guò)濾等操作,它提供了許多參數(shù)來(lái)實(shí)現(xiàn) logger.addHandler 中的配置更加簡(jiǎn)單方便。
其中 sink 是最重要的參數(shù),可以傳入不同的數(shù)據(jù)類型。傳入文件路徑、文件句柄、 sys.stderr 、甚至 logging 模塊的 Handler 如 FileHandler 、 StreamHandler 等,這樣就可以快速實(shí)現(xiàn)自定義的 Handler 配置。
通過(guò)給 remove 方法傳遞 add 方法返回的對(duì)象, 可以刪除 add 方法添加的 sink ,這里的 remove 并不是刪除 test2.log 文件,而是停止向該文件輸出日志,需要需要繼續(xù)記錄日志則需要重新 add 日志文件。
用 rotation 、 retention 、 compression 進(jìn)行日志窗口、更新、壓縮管理。
支持控制臺(tái)輸出添加顏色, 除了基礎(chǔ)色, loguru 甚至允許16進(jìn)制、RGB格式的顏色值和加粗、下劃線等樣式。
使用裝飾器 @logger.catch 可以和 logging 一樣使用 logger.exception 函數(shù)來(lái)記錄異常信息。
使用 exception 方法輸出的異常信息包含堆棧信息和當(dāng)前變量的值,方便問(wèn)題定位。
使用 serialize 可以將日志轉(zhuǎn)換為 JSON 格式, enqueue 可以保證多線程、多進(jìn)程安全。
修改時(shí)間格式。
從事與軟件相關(guān)工作的人,應(yīng)該都聽(tīng)過(guò)“日志”一詞。
日志就是跟蹤軟件運(yùn)行時(shí)事件的方法,為了能夠在程序運(yùn)行過(guò)程中記錄錯(cuò)誤。
通過(guò)日志記錄程序的運(yùn)行,方便我們查詢信息,以便追蹤問(wèn)題、進(jìn)行維護(hù)和調(diào)試、還是數(shù)據(jù)分析。
并且各編程語(yǔ)言都形成了各自的日志體系和相應(yīng)的框架。
日志的作用總結(jié):
首先我們要樹立一個(gè)觀點(diǎn),那就是“不是為了記錄日志而記錄日志,日志也不是隨意記的”。要實(shí)現(xiàn)能夠只通過(guò)日志文件還原整個(gè)程序執(zhí)行的過(guò)程,達(dá)到能透明地看到程序里執(zhí)行情況,每個(gè)線程每個(gè)過(guò)程到底執(zhí)行結(jié)果的目的。日志就像飛機(jī)的黑匣子一樣,應(yīng)當(dāng)能夠復(fù)原異常的整個(gè)現(xiàn)場(chǎng)乃至細(xì)節(jié)。
在項(xiàng)目中,日志這個(gè)功能非常重要,我們要重視起來(lái)。
在Python中,使用logging模塊來(lái)進(jìn)行日志的處理。
logging是Python的內(nèi)置模塊,主要用于將日志信息進(jìn)行格式化內(nèi)容輸出,可將格式化內(nèi)容輸出到文件,也可輸出到屏幕。
我們?cè)陂_發(fā)過(guò)程中,常用print()函數(shù)來(lái)進(jìn)行調(diào)試,但是在實(shí)際應(yīng)用的部署時(shí),我們要將日志信息輸出到文件中,方便后續(xù)查找以及備份。
在我們使用日志管理時(shí),我們也可以將日志格式化成Json對(duì)象轉(zhuǎn)存到ELK中方便圖形化查看及管理。
logging模塊將日志系統(tǒng)從高向低依次定義了四個(gè)類,分別是logger(日志器)、handler(處理器)、filter(過(guò)濾器)和formatter(格式器)。其中由日志器生成的實(shí)例將接管原本日志記錄函數(shù)logging.log的功能。
說(shuō)明:
我們先來(lái)思考下下面的兩個(gè)問(wèn)題:
在軟件開發(fā)階段或部署開發(fā)環(huán)境時(shí),為了盡可能詳細(xì)的查看應(yīng)用程序的運(yùn)行狀態(tài)來(lái)保證上線后的穩(wěn)定性,我們可能需要把該應(yīng)用程序所有的運(yùn)行日志全部記錄下來(lái)進(jìn)行分析,這是非常耗費(fèi)機(jī)器性能的。
當(dāng)應(yīng)用程序正式發(fā)布或在生產(chǎn)環(huán)境部署應(yīng)用程序時(shí),我們通常只需要記錄應(yīng)用程序的異常信息、錯(cuò)誤信息等,這樣既可以減小服務(wù)器的I/O壓力,也可以避免我們?cè)谂挪楣收蠒r(shí)被淹沒(méi)在日志的海洋里。
那么怎樣才能在不改動(dòng)應(yīng)用程序代碼的情況下,根據(jù)事件的重要性或者稱之為等級(jí),實(shí)現(xiàn)在不同的環(huán)境中,記錄不同詳細(xì)程度的日志呢?
這就是日志等級(jí)的作用了,我們通過(guò)配置文件指定我們需要的日志等級(jí)就可以了。
說(shuō)明:
總結(jié):
開發(fā)應(yīng)用程序時(shí)或部署開發(fā)環(huán)境時(shí),可以使用DEBUG或INFO級(jí)別的日志獲取盡可能詳細(xì)的日志信息,可以方便進(jìn)行開發(fā)或部署調(diào)試。 應(yīng)用上線或部署生產(chǎn)環(huán)境時(shí),應(yīng)用使用WARNING或ERROR或CRITICAL級(jí)別的日志,來(lái)降低機(jī)器的I/O壓力和提高獲取錯(cuò)誤日志信息的效率。 日志級(jí)別的指定通常都是在應(yīng)用程序的配置文件中進(jìn)行指定的。 不同的應(yīng)用程序所定義的日志等級(jí)會(huì)有所差別,根據(jù)實(shí)際需求來(lái)決定。
寫本文的目的是我在寫 python 項(xiàng)目的時(shí)候需要記錄日志,我忘記怎么處理了,每次都需要去網(wǎng)上查一遍, 好記性不如爛筆頭 , 這里把查閱的內(nèi)容記錄下來(lái),方便以后查找。
python 項(xiàng)目中記錄日志,可以使用 logging 模塊,logging 模塊定義的函數(shù)和類為應(yīng)用程序和庫(kù)的開發(fā)實(shí)現(xiàn)了一個(gè)靈活的事件日志系統(tǒng)。logging 模塊是Python的一個(gè)標(biāo)準(zhǔn)庫(kù)模塊,由標(biāo)準(zhǔn)庫(kù)模塊提供日志記錄API的關(guān)鍵好處是所有Python模塊都可以使用這個(gè)日志記錄功能。所以,你的應(yīng)用日志可以將你自己的日志信息與來(lái)自第三方模塊的信息整合起來(lái)。
在 __init__.py 文件中做如下配置:
控制臺(tái)輸出日志如下:
參考文檔
def?write_log(username,operation):
'''
寫日志函數(shù)
:param?username:用戶名
:param?operation:用戶的操作信息
:return:
'''
w_time?=?time.strftime('%Y-%m-%d?%H%M%S')
with?open('log.txt','a+')?as?fw:
log_content?=?'%s?%s?%s?\n'%(w_time,username,operation)
fw.write(log_content)
希望對(duì)你有幫助!
日志的作用非常重要,日志可以記錄用戶的操作、程序的異常,還可以為數(shù)據(jù)分析提供依據(jù),日志的存在意義就是為了能夠在程序在運(yùn)行過(guò)程中記錄錯(cuò)誤,方便維護(hù)和調(diào)試,能夠快速定位出錯(cuò)的地方,減少維護(hù)成本。每個(gè)程序員都應(yīng)該知道,不是為了記錄日志而記錄日志,日志也不是隨意記的。要實(shí)現(xiàn)能夠只通過(guò)日志文件還原整個(gè)程序執(zhí)行的過(guò)程,達(dá)到能透明地看到程序里執(zhí)行情況,每個(gè)線程、每個(gè)過(guò)程到底執(zhí)行到哪的目的。日志就像飛機(jī)的黑匣子一樣,應(yīng)當(dāng)能夠復(fù)原異常的整個(gè)現(xiàn)場(chǎng)乃至細(xì)節(jié)!
最常見(jiàn)的是把輸出函數(shù) print() 當(dāng)作日志記錄的方式,直接打印各種提示信息,常見(jiàn)于個(gè)人練習(xí)項(xiàng)目里,通常是懶得單獨(dú)配置日志,而且項(xiàng)目太小不需要日志信息,不需要上線,不需要持續(xù)運(yùn)行,完整的項(xiàng)目不推薦直接打印日志信息,現(xiàn)實(shí)中也幾乎沒(méi)有人這么做。
我們可以在不少小項(xiàng)目里面看到作者自己寫了一個(gè)日志模板,通常利用 print() 或者 sys.stdout 稍微封裝一下即可實(shí)現(xiàn)簡(jiǎn)單的日志輸出,這里的 sys.stdout 是 Python 中的標(biāo)準(zhǔn)輸出流, print() 函數(shù)是對(duì) sys.stdout 的高級(jí)封裝,當(dāng)我們?cè)?Python 中打印對(duì)象調(diào)用 print(obj) 時(shí)候,事實(shí)上是調(diào)用了 sys.stdout.write(obj+'\n') , print() 將內(nèi)容打印到了控制臺(tái),然后追加了一個(gè)換行符 \n 。
自寫日志模板適合比較小的項(xiàng)目,可以按照自己的喜好編寫模板,不需要太多復(fù)雜配置,方便快捷,但是這種記錄日志的方式并不是很規(guī)范,有可能你自己覺(jué)得閱讀體驗(yàn)不錯(cuò),但是別人在接觸你的項(xiàng)目的時(shí)候往往需要花費(fèi)一定的時(shí)間去學(xué)習(xí)日志的邏輯、格式、輸出方式等,比較大的項(xiàng)目同樣不推薦這種方法。
一個(gè)簡(jiǎn)單的自寫日志模板舉例:
日志模板 log.py:
調(diào)用日志模塊:
日志輸出:
在一個(gè)完整的項(xiàng)目中,大多數(shù)人都會(huì)引入專門的日志記錄庫(kù),而 Python 自帶的標(biāo)準(zhǔn)庫(kù) logging 就是專門為日志記錄而生的,logging 模塊定義的函數(shù)和類為應(yīng)用程序和庫(kù)的開發(fā)實(shí)現(xiàn)了一個(gè)靈活的事件日志系統(tǒng)。由標(biāo)準(zhǔn)庫(kù)模塊提供日志記錄 API 的關(guān)鍵好處是所有 Python 模塊都可以使用這個(gè)日志記錄功能。所以,你的應(yīng)用日志可以將你自己的日志信息與來(lái)自第三方模塊的信息整合起來(lái)。
logging 模塊雖然強(qiáng)大,但是其配置也是比較繁瑣的,在大型項(xiàng)目中通常需要單獨(dú)初始化日志、配置日志格式等等,K哥在日常使用中通常都會(huì)對(duì) logging 做如下的封裝寫法,使日志可以按天保存,保留15天的日志,可以配置是否輸出到控制臺(tái)和文件,如下所示:
輸出日志:
它在控制臺(tái)中是這樣的:
當(dāng)然,如果你不需要很復(fù)雜的功能,希望簡(jiǎn)潔一點(diǎn),僅僅需要在控制臺(tái)輸出一下日志的話,也可以只進(jìn)行簡(jiǎn)單的配置:
對(duì)于 logging 模塊,即便是簡(jiǎn)單的使用,也需要自己定義格式,這里介紹一個(gè)更加優(yōu)雅、高效、簡(jiǎn)潔的第三方模塊:loguru,官方的介紹是:Loguru is a library which aims to bring enjoyable logging in Python. Loguru 旨在為 Python 帶來(lái)愉快的日志記錄。這里引用官方的一個(gè) GIF 來(lái)快速演示其功能:
Loguru 僅支持 Python 3.5 及以上的版本,使用 pip 安裝即可:
Loguru 的主要概念是只有一個(gè):logger
控制臺(tái)輸出:
可以看到不需要手動(dòng)設(shè)置,Loguru 會(huì)提前配置一些基礎(chǔ)信息,自動(dòng)輸出時(shí)間、日志級(jí)別、模塊名、行號(hào)等信息,而且根據(jù)等級(jí)的不同,還自動(dòng)設(shè)置了不同的顏色,方便觀察,真正做到了開箱即用!
如果想自定義日志級(jí)別,自定義日志格式,保存日志到文件該怎么辦?與 logging 模塊不同,不需要 Handler,不需要 Formatter,只需要一個(gè) add() 函數(shù)就可以了,例如我們想把日志儲(chǔ)存到文件:
我們不需要像 logging 模塊一樣再聲明一個(gè) FileHandler 了,就一行 add() 語(yǔ)句搞定,運(yùn)行之后會(huì)發(fā)現(xiàn)目錄下 test.log 里面同樣出現(xiàn)了剛剛控制臺(tái)輸出的 debug 信息。
與 add() 語(yǔ)句相反, remove() 語(yǔ)句可以刪除我們添加的配置:
此時(shí)控制臺(tái)會(huì)輸出兩條 debug 信息:
而 test.log 日志文件里面只有一條 debug 信息,原因就在于我們?cè)诘诙l debug 語(yǔ)句之前使用了 remove() 語(yǔ)句。
Loguru 對(duì)輸出到文件的配置有非常強(qiáng)大的支持,比如支持輸出到多個(gè)文件,分級(jí)別分別輸出,過(guò)大創(chuàng)建新文件,過(guò)久自動(dòng)刪除等等。 下面我們來(lái)詳細(xì)看一下 add() 語(yǔ)句的詳細(xì)參數(shù):
基本語(yǔ)法:
基本參數(shù)釋義:
當(dāng)且僅當(dāng) sink 是協(xié)程函數(shù)時(shí),以下參數(shù)適用:
當(dāng)且僅當(dāng) sink 是文件路徑時(shí),以下參數(shù)適用:
這么多參數(shù)可以見(jiàn)識(shí)到 add() 函數(shù)的強(qiáng)大之處,僅僅一個(gè)函數(shù)就能實(shí)現(xiàn) logging 模塊的諸多功能,接下來(lái)介紹幾個(gè)比較常用的方法。
add() 函數(shù)的 rotation 參數(shù),可以實(shí)現(xiàn)按照固定時(shí)間創(chuàng)建新的日志文件,比如設(shè)置每天 0 點(diǎn)新創(chuàng)建一個(gè) log 文件:
設(shè)置超過(guò) 500 MB 新創(chuàng)建一個(gè) log 文件:
設(shè)置每隔一個(gè)周新創(chuàng)建一個(gè) log 文件:
add() 函數(shù)的 retention 參數(shù),可以設(shè)置日志的最長(zhǎng)保留時(shí)間,比如設(shè)置日志文件最長(zhǎng)保留 15 天:
設(shè)置日志文件最多保留 10 個(gè):
也可以是一個(gè) datetime.timedelta 對(duì)象,比如設(shè)置日志文件最多保留 5 個(gè)小時(shí):
add() 函數(shù)的 compression 參數(shù),可以配置日志文件的壓縮格式,這樣可以更加節(jié)省存儲(chǔ)空間,比如設(shè)置使用 zip 文件格式保存:
其格式支持: gz 、 bz2 、 xz 、 lzma 、 tar 、 tar.gz 、 tar.bz2 、 tar.xz
Loguru 在輸出 log 的時(shí)候還提供了非常友好的字符串格式化功能,相當(dāng)于 str.format() :
輸出:
在 Loguru 里可以直接使用它提供的裝飾器就可以直接進(jìn)行異常捕獲,而且得到的日志是無(wú)比詳細(xì)的:
日志輸出:
在控制臺(tái)的輸出是這樣的:
相比 Logging,Loguru 無(wú)論是在配置方面、日志輸出樣式還是異常追蹤,都遠(yuǎn)優(yōu)于 Logging,使用 Loguru 無(wú)疑能提升開發(fā)人員效率。本文僅介紹了一些常用的方法,想要詳細(xì)了解可參考 Loguru 官方文檔 或關(guān)注 Loguru GitHub 。