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默認配置了一套日志輸出格式,有時間、級別、模塊名、行號以及日志信息,不需要手動創建 logger,直接使用即可,另外其輸出還是彩色的,看起來會更加友好。所以我們不需要提前配置什么,直接用就可以。
2.2、add()函數
No Handler、no Formatter、no Filter:one function to rule them all。
在使用logging模塊是,我們需要手動配置Handler、Formatter以及Filter,需要調用不同的函數進行配置,但是在loguru中,只需要一個add()函數即可。通過add()函數,我們可以設置Handler,設置Formatter,Filter 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()函數指明了Handler為控制台輸出,指定了format的格式,以及filter和level。然后就可以輸出日志信息了:

add()函數原型定義如下:
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
里面有好多參數可以用來配置不同的屬性。 這里面有一個非常重要的參數sink。通過 sink 我們可以傳入多種不同的數據結構,匯總如下:
sink 可以傳入一個 file 對象,例如 sys.stderr 或者 open('file.log', 'w') 都可以。
sink 可以直接傳入一個 str 字符串或者 pathlib.Path 對象,其實就是代表文件路徑的,如果識別到是這種類型,它會自動創建對應路徑的日志文件並將日志輸出進去。
sink 可以是一個方法,可以自行定義輸出實現。
sink 可以是一個 logging 模塊的 Handler,比如 FileHandler、StreamHandler 等等,這樣就可以實現自定義 Handler 的配置。
sink 還可以是一個自定義的類,具體的實現規范可以參見官方文檔。
2.3、創建記錄日志文件
Easier file logging with rotation / retention / compression。
2.3.1、創建日志文件
我們可以通過傳入一個文件名字符串或者文件路徑,loguru就會自動創建一個日志文件,如下所示:
from loguru import logger logger.add("runtime.log") # 創建了一個文件名為runtime的log文件 logger.debug("This's a log message in file")
上面的程序就會在程序文件所在目錄下創建一個名為runtime.log的文件,而且會在文件中記錄日志:

同時也會在控制台輸出日志信息:

如果不想在控制台也輸出日志信息,因為logger是默認輸出至stderr的,所以只需要在之前把它給remove掉就好了:
from loguru import logger logger.remove(handler_id=None) logger.add("runtime.log") # 創建了一個文件名為runtime的log文件 logger.debug("This's a log message in file")
這樣就不會在控制台輸出日志信息了。
2.3.2、指定創建日志文件名
在add()創建日志文件的時候,可以通過添加占位符的方式添加文件的日期,如下所示:
from loguru import logger logger.add("runtime_{time}.log") # 創建了一個文件名為runtime的log文件 logger.debug("This's a log message in file")
這樣就會創建一個帶有日期的log文件。
2.3.3、rotation 滾動記錄日志文件
通過配置rotation參數,指定日志文件滾動記錄的條件,如下所示:
1)、
logger.add("file_1.log", rotation="500 MB") # Automatically rotate too big file
通過這樣的配置我們就可以實現每 500MB 存儲一個文件,每個 log 文件過大就會新創建一個新的 log 文件。我們可以在創建文件的時候加一個(time)占位符,這樣在生成時可以自動將時間替換進去,生成一個文件名包含時間的 log 文件。
2)、
logger.add("file_2.log", rotation="12:00") # New file is created each day at noon
通過上面的配置,可以實現沒填中午12:00創建一個log文件輸出了。
3)、
logger.add("file_3.log", rotation="1 week") # Once the file is too old, it's rotated
通過上面的配置可以實現每隔1周創建一個新的log文件輸出了。
2.3.4、retention 指定日志保留時長
通過配置retention參數,可以指定日志的保留時長:
logger.add("file_X.log", retention="10 days") # Cleanup after some time
通過上面的配置,就可以指定日志最多保留10天,每隔10天之后就會清理舊的日志,這樣就不會造成內存浪費。
2.3.4、compression 配置文件壓縮格式
通過配置compression參數可以指定日志文件的壓縮格式:
logger.add("file_Y.log", compression="zip") # Save some loved space
通過上面的配置,可以指定日志文件的壓縮格式為zip格式,可以節省存儲空間。
2.4、異常捕獲
Exceptions catching within threads or main。
最讓我感到loguru模塊功能強大的地方就是它的異常捕獲功能。如果程序在運行過程出現崩潰或錯誤,記錄日志是我們回溯程序執行過程的一個重要方式,但是很多時候,根據日志並不知道程序為什么出錯或者看不出來程序具體出錯在哪些地方,此時如果我們能在日志中記錄當異常發生時的情況或者信息,那么多我們解決程序問題來說,簡直事半功倍。
在loguru模塊中,異常的捕獲有兩種方式:
2.4.1、catch裝飾器 方法
通過catch裝飾器的方式實現異常捕獲:
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裝飾器對函數my_function進行裝飾,這樣,當該函數出現異常時,就會打印出異常日志信息,如下所示:

在日志信息中,不僅指明了異常出現的地方,而且把參數的值也記錄下來了。
2.4.2、exception 方法
通過exception方法也可以實現異常的捕獲與記錄:
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文件中使用的,而且不會出現沖突:
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()函數是一個特殊的函數,只有這個模塊從命令行直接運行時才會執行該函數(不能被其他模塊導入) ''' def _main(): for pause in loops: Thread(target=loop, args=(pause,)).start() ''' 這個函數(裝飾器的方式)會在python解釋器中注冊一個退出函數,也就是說,他會在腳本退出之前請求調用這個特殊函數 ''' @register def _atexit(): logger.info("All Thread DONE!") logger.info("\n===========================================================================\n") if __name__=='__main__': logger.add("run.log") _main()
日志記錄文件如下所示:

上面代碼創建了3個線程,每個線程都正確打印出了日志信息。
————————————————
版權聲明:本文為CSDN博主「bailang_zhizun」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/bailang_zhizun/article/details/107863671
