Python 日志管理模塊Loguru的用法小結
python的日志管理模塊可以用自帶的logging模塊,也可以用第三方的Loguru模塊,關于logging和loguru模塊的簡單使用可以參考以下文章,寫的還是不錯的:logging 和 loguru的使用
關于logging模塊的詳細使用,可以參考這篇文章:logging模塊詳細使用。
本片文章只記錄loguru模塊的使用,包括簡單的用法,以及在多模塊和多線程下的使用。
1、loguru的安裝
1.1、pip安裝
pip\pip3 install loguru
1.2、pycharm下安裝
2、loguru的簡單使用
2.1、使用非常簡單
Use out of box without boilerplate。
loguru的用法非常簡單,在 loguru 中有且僅有一個對象:logger。為了使用方便,logger在使用時,是提前配置好的,并且開始是默認輸出至stderr(但是這些完全是可以再進行配置的),而且打印出的log信息默認是配置了顏色的。如下所示,loguru的使用真的是非常簡單:
from loguru import logger logger.debug("This's a log message")
上面的日志記錄語句,默認向stderr(控制臺)打印了一條輸出語句,輸出結果如下所示:
可以看出,loguru默認配置了一套日志輸出格式,有時間、級別、模塊名、行號以及日志信息,不需要手動創(chuàng)建 logger,直接使用即可,另外其輸出還是彩色的,看起來會更加友好。所以我們不需要提前配置什么,直接用就可以。
2.2、add()函數(shù)
No Handler、no Formatter、no Filter:one function to rule them all。
在使用logging模塊是,我們需要手動配置Handler、Formatter以及Filter,需要調(diào)用不同的函數(shù)進行配置,但是在loguru中,只需要一個add()函數(shù)即可。通過add()函數(shù),我們可以設置Handler,設置Formatter,F(xiàn)ilter Message以及設置Level。使用示例:
import sys from loguru import logger logger.add(sys.stderr, format="{time} {level} {message}", filter="my_module", level="INFO") logger.debug("This's a new log message")
在上述代碼中,通過add()函數(shù)指明了Handler為控制臺輸出,指定了format的格式,以及filter和level。然后就可以輸出日志信息了:
add()函數(shù)原型定義如下:
def add( self, sink, *, level=_defaults.LOGURU_LEVEL, format=_defaults.LOGURU_FORMAT, filter=_defaults.LOGURU_FILTER, colorize=_defaults.LOGURU_COLORIZE, serialize=_defaults.LOGURU_SERIALIZE, backtrace=_defaults.LOGURU_BACKTRACE, diagnose=_defaults.LOGURU_DIAGNOSE, enqueue=_defaults.LOGURU_ENQUEUE, catch=_defaults.LOGURU_CATCH, **kwargs ): pass
里面有好多參數(shù)可以用來配置不同的屬性。 這里面有一個非常重要的參數(shù)sink。通過 sink 我們可以傳入多種不同的數(shù)據(jù)結構,匯總如下:
- sink 可以傳入一個 file 對象,例如
sys.stderr
或者open('file.log', 'w')
都可以。 - sink 可以直接傳入一個
str
字符串或者pathlib.Path
對象,其實就是代表文件路徑的,如果識別到是這種類型,它會自動創(chuàng)建對應路徑的日志文件并將日志輸出進去。 - sink 可以是一個方法,可以自行定義輸出實現(xiàn)。
- sink 可以是一個 logging 模塊的 Handler,比如 FileHandler、StreamHandler 等等,這樣就可以實現(xiàn)自定義 Handler 的配置。sink 還可以是一個自定義的類,具體的實現(xiàn)規(guī)范可以參見官方文檔。
2.3、創(chuàng)建記錄日志文件
Easier file logging with rotation / retention / compression。
2.3.1、創(chuàng)建日志文件
我們可以通過傳入一個文件名字符串或者文件路徑,loguru就會自動創(chuàng)建一個日志文件,如下所示:
from loguru import logger logger.add("runtime.log") # 創(chuàng)建了一個文件名為runtime的log文件 logger.debug("This's a log message in file")
上面的程序就會在程序文件所在目錄下創(chuàng)建一個名為runtime.log的文件,而且會在文件中記錄日志:
同時也會在控制臺輸出日志信息:
如果不想在控制臺也輸出日志信息,因為logger是默認輸出至stderr的,所以只需要在之前把它給remove掉就好了:
from loguru import logger logger.remove(handler_id=None) logger.add("runtime.log") # 創(chuàng)建了一個文件名為runtime的log文件 logger.debug("This's a log message in file")
這樣就不會在控制臺輸出日志信息了。
2.3.2、指定創(chuàng)建日志文件名
在add()創(chuàng)建日志文件的時候,可以通過添加占位符的方式添加文件的日期,如下所示:
from loguru import logger logger.add("runtime_{time}.log") # 創(chuàng)建了一個文件名為runtime的log文件 logger.debug("This's a log message in file")
這樣就會創(chuàng)建一個帶有日期的log文件。
2.3.3、rotation 滾動記錄日志文件
通過配置rotation參數(shù),指定日志文件滾動記錄的條件,如下所示:
1)、
logger.add("file_1.log", rotation="500 MB") # Automatically rotate too big file
通過這樣的配置我們就可以實現(xiàn)每 500MB 存儲一個文件,每個 log 文件過大就會新創(chuàng)建一個新的 log 文件。我們可以在創(chuàng)建文件的時候加一個(time)占位符,這樣在生成時可以自動將時間替換進去,生成一個文件名包含時間的 log 文件。
2)、
logger.add("file_2.log", rotation="12:00") # New file is created each day at noon
通過上面的配置,可以實現(xiàn)沒填中午12:00創(chuàng)建一個log文件輸出了。
3)、
logger.add("file_3.log", rotation="1 week") # Once the file is too old, it's rotated
通過上面的配置可以實現(xiàn)每隔1周創(chuàng)建一個新的log文件輸出了。
2.3.4、retention 指定日志保留時長
通過配置retention參數(shù),可以指定日志的保留時長:
logger.add("file_X.log", retention="10 days") # Cleanup after some time
通過上面的配置,就可以指定日志最多保留10天,每隔10天之后就會清理舊的日志,這樣就不會造成內(nèi)存浪費。
2.3.4、compression 配置文件壓縮格式
通過配置compression參數(shù)可以指定日志文件的壓縮格式:
logger.add("file_Y.log", compression="zip") # Save some loved space
通過上面的配置,可以指定日志文件的壓縮格式為zip格式,可以節(jié)省存儲空間。
2.4、異常捕獲
Exceptions catching within threads or main。
最讓我感到loguru模塊功能強大的地方就是它的異常捕獲功能。如果程序在運行過程出現(xiàn)崩潰或錯誤,記錄日志是我們回溯程序執(zhí)行過程的一個重要方式,但是很多時候,根據(jù)日志并不知道程序為什么出錯或者看不出來程序具體出錯在哪些地方,此時如果我們能在日志中記錄當異常發(fā)生時的情況或者信息,那么多我們解決程序問題來說,簡直事半功倍。
在loguru模塊中,異常的捕獲有兩種方式:
2.4.1、catch裝飾器 方法
通過catch裝飾器的方式實現(xiàn)異常捕獲:
from loguru import logger logger.add("runtime.log") @logger.catch def my_function(x, y, z): return 1 / (x + y + z) # An error? It's caught anyway! my_function(0, 0, 0)
上面的代碼中,通過catch裝飾器對函數(shù)my_function進行裝飾,這樣,當該函數(shù)出現(xiàn)異常時,就會打印出異常日志信息,如下所示:
在日志信息中,不僅指明了異常出現(xiàn)的地方,而且把參數(shù)的值也記錄下來了。
2.4.2、exception 方法
通過exception方法也可以實現(xiàn)異常的捕獲與記錄:
from loguru import logger logger.add("runtime.log") def my_function1(x, y, z): try: return 1 / (x + y + z) except ZeroDivisionError: logger.exception("What?!") my_function1(0, 0, 0)
記錄的日志信息如下所示:
3、loguru在多模塊情況下的使用
Asynchronous, Thread-safe, Multiprocess-safe。
由于在 loguru 中有且僅有一個對象:logger。所以loguru是可以在多塊module文件中使用的,而且不會出現(xiàn)沖突:
exceptions_catching2_03.py:
from loguru import logger def func(a, b): logger.info("Process func") return a / b def nested(c): try: func(5, c) except ZeroDivisionError: logger.exception("What?!")
test.py:
#coding:utf-8 from loguru import logger import exceptions_catching2_03 as ec3 if __name__=='__main__': logger.add("run.log") logger.info("Start!") ec3.nested(0) logger.info("End!")
運行結果如下所示:
4、loguru在多線程情況下的使用
Asynchronous, Thread-safe, Multiprocess-safe
所有添加至logger的sink默認都是線程安全的,所以loguru也可以很安全的在多線程的情形下使用:
#coding:utf-8 from atexit import register from random import randrange from threading import Thread, Lock, current_thread from time import sleep, ctime from loguru import logger class CleanOutputSet(set): def __str__(self): return ','.join(x for x in self) lock = Lock() loops = (randrange(2, 5) for x in range(randrange(3, 7))) remaining = CleanOutputSet() def loop(nsec): myname = current_thread().name logger.info("Startted {}", myname) ''' 鎖的申請和釋放交給with上下文管理器 ''' with lock: remaining.add(myname) sleep(nsec) logger.info("Completed {} ({} secs)", myname, nsec) with lock: remaining.remove(myname) logger.info("Remaining:{}", (remaining or 'NONE')) ''' _main()函數(shù)是一個特殊的函數(shù),只有這個模塊從命令行直接運行時才會執(zhí)行該函數(shù)(不能被其他模塊導入) ''' def _main(): for pause in loops: Thread(target=loop, args=(pause,)).start() ''' 這個函數(shù)(裝飾器的方式)會在python解釋器中注冊一個退出函數(shù),也就是說,他會在腳本退出之前請求調(diào)用這個特殊函數(shù) ''' @register def _atexit(): logger.info("All Thread DONE!") logger.info("\n===========================================================================\n") if __name__=='__main__': logger.add("run.log") _main()
日志記錄文件如下所示:
上面代碼創(chuàng)建了3個線程,每個線程都正確打印出了日志信息。
到此這篇關于Python 日志管理模塊Loguru的用法小結的文章就介紹到這了,更多相關Python 日志管理模塊 Loguru內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Python利用yield?form實現(xiàn)異步協(xié)程爬蟲
這篇文章主要為大家詳細介紹了Python如何利用yield?form實現(xiàn)異步協(xié)程爬蟲。其實這是很古老的用法了,現(xiàn)在大多用的aiohttp庫實現(xiàn),這篇記錄僅僅用做個人的協(xié)程底層實現(xiàn)的學習,希望對大家有所幫助2022-11-11python爬蟲MeterSphere平臺執(zhí)行報告流程解析
這篇文章主要為大家介紹了python爬蟲MeterSphere平臺執(zhí)行報告流程解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-12-12tensorflow入門之訓練簡單的神經(jīng)網(wǎng)絡方法
本篇文章主要介紹了tensorflow入門之訓練簡單的神經(jīng)網(wǎng)絡方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-02-02Django項目配置連接多個數(shù)據(jù)庫的方法記錄
最近在進行django項目開發(fā)的時候,遇到了需要連接兩個MySQL數(shù)據(jù)庫的問題,下面這篇文章主要給大家介紹了關于Django項目配置連接多個數(shù)據(jù)庫的相關資料,需要的朋友可以參考下2022-05-05Python循環(huán)語句For?Range用法示例詳解
這篇文章主要為大家介紹了Python循環(huán)語句For?Range用法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-09-09Python+Selenium實現(xiàn)在Geoserver批量發(fā)布Mongo矢量數(shù)據(jù)
這篇文章主要為大家詳細介紹了如何利用Python+Selenium實現(xiàn)在 Geoserver批量發(fā)布來自Mongo中的矢量數(shù)據(jù),文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下2022-07-07