Python 日志管理模塊Loguru的用法小結(jié)
python的日志管理模塊可以用自帶的logging模塊,也可以用第三方的Loguru模塊,關(guān)于logging和loguru模塊的簡單使用可以參考以下文章,寫的還是不錯的:logging 和 loguru的使用
關(guān)于logging模塊的詳細(xì)使用,可以參考這篇文章:logging模塊詳細(xì)使用。
本片文章只記錄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在使用時,是提前配置好的,并且開始是默認(rèn)輸出至stderr(但是這些完全是可以再進(jìn)行配置的),而且打印出的log信息默認(rèn)是配置了顏色的。如下所示,loguru的使用真的是非常簡單:
from loguru import logger logger.debug("This's a log message")
上面的日志記錄語句,默認(rèn)向stderr(控制臺)打印了一條輸出語句,輸出結(jié)果如下所示:
可以看出,loguru默認(rèn)配置了一套日志輸出格式,有時間、級別、模塊名、行號以及日志信息,不需要手動創(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ù)進(jìn)行配置,但是在loguru中,只需要一個add()函數(shù)即可。通過add()函數(shù),我們可以設(shè)置Handler,設(shè)置Formatter,F(xiàn)ilter Message以及設(shè)置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ù)結(jié)構(gòu),匯總?cè)缦拢?/p>
- sink 可以傳入一個 file 對象,例如
sys.stderr
或者open('file.log', 'w')
都可以。 - sink 可以直接傳入一個
str
字符串或者pathlib.Path
對象,其實(shí)就是代表文件路徑的,如果識別到是這種類型,它會自動創(chuàng)建對應(yīng)路徑的日志文件并將日志輸出進(jìn)去。 - sink 可以是一個方法,可以自行定義輸出實(shí)現(xiàn)。
- sink 可以是一個 logging 模塊的 Handler,比如 FileHandler、StreamHandler 等等,這樣就可以實(shí)現(xiàn)自定義 Handler 的配置。sink 還可以是一個自定義的類,具體的實(shí)現(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的文件,而且會在文件中記錄日志:
同時也會在控制臺輸出日志信息:
如果不想在控制臺也輸出日志信息,因?yàn)閘ogger是默認(rèn)輸出至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
通過這樣的配置我們就可以實(shí)現(xiàn)每 500MB 存儲一個文件,每個 log 文件過大就會新創(chuàng)建一個新的 log 文件。我們可以在創(chuàng)建文件的時候加一個(time)占位符,這樣在生成時可以自動將時間替換進(jìn)去,生成一個文件名包含時間的 log 文件。
2)、
logger.add("file_2.log", rotation="12:00") # New file is created each day at noon
通過上面的配置,可以實(shí)現(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
通過上面的配置可以實(shí)現(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)存浪費(fè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模塊功能強(qiáng)大的地方就是它的異常捕獲功能。如果程序在運(yùn)行過程出現(xiàn)崩潰或錯誤,記錄日志是我們回溯程序執(zhí)行過程的一個重要方式,但是很多時候,根據(jù)日志并不知道程序?yàn)槭裁闯鲥e或者看不出來程序具體出錯在哪些地方,此時如果我們能在日志中記錄當(dāng)異常發(fā)生時的情況或者信息,那么多我們解決程序問題來說,簡直事半功倍。
在loguru模塊中,異常的捕獲有兩種方式:
2.4.1、catch裝飾器 方法
通過catch裝飾器的方式實(shí)現(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進(jìn)行裝飾,這樣,當(dāng)該函數(shù)出現(xiàn)異常時,就會打印出異常日志信息,如下所示:
在日志信息中,不僅指明了異常出現(xiàn)的地方,而且把參數(shù)的值也記錄下來了。
2.4.2、exception 方法
通過exception方法也可以實(shí)現(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!")
運(yùn)行結(jié)果如下所示:
4、loguru在多線程情況下的使用
Asynchronous, Thread-safe, Multiprocess-safe
所有添加至logger的sink默認(rèn)都是線程安全的,所以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ù),只有這個模塊從命令行直接運(yùn)行時才會執(zhí)行該函數(shù)(不能被其他模塊導(dǎo)入) ''' 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個線程,每個線程都正確打印出了日志信息。
到此這篇關(guān)于Python 日志管理模塊Loguru的用法小結(jié)的文章就介紹到這了,更多相關(guān)Python 日志管理模塊 Loguru內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python OpenCV學(xué)習(xí)之圖像濾波詳解
圖像濾波的作用簡單來說就是將一副圖像通過濾波器得到另一幅圖像;明確一個概念,濾波器又被稱為卷積核,濾波的過程又被稱為卷積;實(shí)際上深度學(xué)習(xí)就是訓(xùn)練許多適應(yīng)任務(wù)的濾波器,本質(zhì)上就是得到最佳的參數(shù)。下面來跟隨小編一起深入了解一下圖像濾波吧2022-01-01python實(shí)現(xiàn)跨域代理服務(wù)器的方法
這篇文章主要介紹了python實(shí)現(xiàn)跨域代理服務(wù)器的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-07-07Android模擬器無法啟動,報錯:Cannot set up guest memory ‘a(chǎn)ndroid_arm’ I
這篇文章主要介紹了Android模擬器無法啟動,報錯:Cannot set up guest memory ‘a(chǎn)ndroid_arm’ Invalid argument的解決方法,通過模擬器ram設(shè)置的調(diào)整予以解決,需要的朋友可以參考下2016-07-07幾行代碼讓 Python 函數(shù)執(zhí)行快 30 倍
Python 編程語言,與其他流行編程語言相比主要缺點(diǎn)是它的動態(tài)特性和多功能屬性拖慢了速度表現(xiàn)。Python 代碼是在運(yùn)行時被解釋的,而不是在編譯時被編譯為原生代碼。在本文中,我們將討論如何用多處理模塊并行執(zhí)行自定義 Python 函數(shù),并進(jìn)一步對比運(yùn)行時間指標(biāo)。2021-10-10Python獲取CMD環(huán)境變量值的完整實(shí)現(xiàn)指南
環(huán)境變量是操作系統(tǒng)中用于配置程序運(yùn)行環(huán)境的全局變量,Python?提供了多種方式讀取環(huán)境變量,下面我們就來看看如何使用Python獲取CMD環(huán)境變量值吧2025-06-06