溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Python logging模塊

發(fā)布時間:2020-07-07 18:02:10 來源:網(wǎng)絡 閱讀:1242 作者:LJ_baby 欄目:編程語言

logging模塊簡介

logging模塊是Python的一個標準庫模塊,開發(fā)過程中,可以通過該模塊,靈活的完成日志的記錄。

logging模塊提供了兩種記錄日志的方式:
????1)使用logging提供的模塊級別的函數(shù)(logging.basicConfig,logging.debug,logging.info...)
????2)使用logging模塊的組件(loggers,handlers,filters,formatters)

下面會分別介紹這兩種方式,這里建議使用第二種方式,使用 logging模塊的組件可以更靈活的完成日志記錄~

logging模塊的日志級別

logging模塊的日志級別(level)包括:DEBUG,INFO,WARNING,ERROR,CRITICAL~

日志級別(level) 描述
DEBUG 調(diào)試級別,一般用于問題的排查,日志的信息最為詳細
INFO 僅記錄普通的信息,日志信息的詳細程度僅次于DEBUG
WARNING 警告信息,一般這類信息不會影響程序的正常運行
ERROR 錯誤信息, 出現(xiàn)錯誤信息時,程序一般已不能正常運行
CRITICAL 更嚴重的錯誤信息,程序不能繼續(xù)運行

從 DEBUG 到 CRITICAL,日志等級依次提高,即嚴重性逐步提升,日志的信息量依次減少:
DEBUG < INFO < WARNING < ERROR < CRITICAL

通過logging模塊級別的函數(shù)記錄日志

示例如下:

import logging  
logging.debug('debug message')  
logging.info('info message')  
logging.warning('warning message')  
logging.error('error message')  
logging.critical('critical message')  

輸出結果:
WARNING:root:warning message     # 默認的日志格式:日志級別 : Logger名稱 : 用戶輸出消息。
ERROR:root:error message
CRITICAL:root:critical message

這里僅輸出了大于等于WARNING級別的日志,說明 logging模塊 默認的日志級別為WARNING,即日志級別大于等于WARNING的才會被輸出,且默認情況下,日志會直接打印到標準輸出中~
?
通過 logging模塊 的basicConfig函數(shù)可靈活地配置日志級別,日志格式以及日志的輸出位置:

import logging

logging.basicConfig(level=logging.DEBUG, 
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',                       # 日志格式
                    datefmt='%Y-%m-%d %H:%M:%S',    # 時間格式:2018-11-12 23:50:21
                    filename='/tmp/test.log',    # 日志的輸出路徑
                    filemode='a')                      # 追加模式

logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')

程序運行后,日志信息會直接記錄到 指定的文件中(/tmp/test.log),且日志級別為DEBUG,所以所有的日志都會被輸出,日志信息如下:

?  ~ cat /tmp/test.log

2018-11-12 23:50:49 test.py[line:9] DEBUG debug message
2018-11-12 23:50:49 test.py[line:10] INFO info message
2018-11-12 23:50:49 test.py[line:11] WARNING warning message
2018-11-12 23:50:49 test.py[line:12] ERROR error message
2018-11-12 23:50:49 test.py[line:13] CRITICAL critical message

?
logging.basicConfig()函數(shù)中可通過具體參數(shù)來更改logging模塊默認行為,可用參數(shù)有:

filename:用指定的文件名創(chuàng)建FiledHandler,這樣日志會被存儲在指定的文件中。
filemode:文件打開方式,在指定了filename時使用這個參數(shù),默認值為“a”還可指定為“w”。
format:指定handler使用的日志顯示格式。
datefmt:指定日期時間格式。
level:設置rootlogger(后邊會講解具體概念)的日志級別
stream:用指定的stream創(chuàng)建StreamHandler。可以指定輸出到sys.stderr,sys.stdout或者文件(f=open(‘test.log’,’w’)),默認為sys.stderr。若同時列出了filename和stream兩個參數(shù),則stream參數(shù)會被忽略。
?
format參數(shù)中可能用到的格式化串:
%(name)s Logger的名字
%(levelno)s 數(shù)字形式的日志級別
%(levelname)s 文本形式的日志級別
%(pathname)s 調(diào)用日志輸出函數(shù)的模塊的完整路徑名,可能沒有
%(filename)s 調(diào)用日志輸出函數(shù)的模塊的文件名
%(module)s 調(diào)用日志輸出函數(shù)的模塊名
%(funcName)s 調(diào)用日志輸出函數(shù)的函數(shù)名
%(lineno)d 調(diào)用日志輸出函數(shù)的語句所在的代碼行
%(created)f 當前時間,用UNIX標準的表示時間的浮 點數(shù)表示
%(relativeCreated)d 輸出日志信息時的,自Logger創(chuàng)建以 來的毫秒數(shù)
%(asctime)s 字符串形式的當前時間。默認格式是 “2018-11-13 00:00:00,896”。逗號后面的是毫秒
%(thread)d 線程ID??赡軟]有
%(threadName)s 線程名??赡軟]有
%(process)d 進程ID??赡軟]有
%(message)s用戶輸出的消息

通過logging模塊的組件記錄日志

使用logging模塊級別的函數(shù)記錄日志,無法實現(xiàn)將日志輸出到多個路徑下。這里logging模塊提供了4個組件,通過這些組件可實現(xiàn)將日志輸出到多個路徑下,且每個路徑下的日志格式可單獨配置~

logging模塊中用于記錄日志的4大組件

組件名稱 功能描述
Logger 日志器,提供了應用程序可一直使用的接口
Handler 將 logger 產(chǎn)生的日志發(fā)送到指定的路徑下(例如可以是終端,也可以是文件)
Filter 若有多個 Logger,可根據(jù)名稱過濾出指定的 Logger 來記錄日志
Formatter 定義日志格式

logging模塊組件的使用

使用組件記錄日志的大致步驟如下:
1)logging.getLogger() 獲取 logger對象
2)創(chuàng)建一個或多個 handler,用于指定日志信息的輸出流向
3)創(chuàng)建一個或多個 formatter,指定日志的格式,并分別將 formatter 綁定到 上
4)將 handler 綁定到 logger對象 上
5)logger.setLevel(logging.DEBUG) 設置日志級別
5)最后便可使用 logger對象 記錄日志~
?
示例

import logging

# 獲取 logger對象
logger = logging.getLogger()

# 創(chuàng)建一個 handler,用于寫入日志文件
fh = logging.FileHandler('/tmp/test.log')

# 再創(chuàng)建一個 handler,用于輸出到控制臺
ch = logging.StreamHandler()

# 創(chuàng)建一個 formatter,兩個 handler 使用相同的日志格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# 綁定 formatter 到 handler 上
fh.setFormatter(formatter)
ch.setFormatter(formatter)

# 綁定 handler 到 logger對象 上
logger.addHandler(fh) #logger對象可以添加多個fh和ch對象
logger.addHandler(ch)

# 設置日志級別
logger.setLevel(logging.WARNING)

logger.debug('logger debug message')
logger.info('logger info message')
logger.warning('logger warning message')
logger.error('logger error message')
logger.critical('logger critical message')

查看輸出結果:

終端輸出:
2018-11-13 23:14:09,161 - root - WARNING - logger warning message
2018-11-13 23:14:09,161 - root - ERROR - logger error message
2018-11-13 23:14:09,161 - root - CRITICAL - logger critical message

文件輸出:
?  ~ cat /tmp/test.log
2018-11-13 23:14:09,161 - root - WARNING - logger warning message
2018-11-13 23:14:09,161 - root - ERROR - logger error message
2018-11-13 23:14:09,161 - root - CRITICAL - logger critical message

也可以通過 handler 來設置日志級別,當使用 handler 來設置日志級別時,存在如下兩種情況:
???1)若 handler 設置的日志級別小于等于 logger 的日志級別時,則以logger 的日志級別為準;
???2)若 handler 設置的日志級別大于 logger 的日志級別時,則以handler 的日志級別為準;
簡單而言就是,兩者同時設置日志級別,以日志級別高的為準。由于不設置 logger 的日志級別,其默認日志級別就是 WARNING,所以不存在 handler 單獨設置日志級別的情況~

通過示例來驗證:
1)logger 日志級別設置為 DEBUG,logger 不設置(默認為WARNING)

import logging

logger = logging.getLogger()
ch = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

ch.setLevel(logging.DEBUG)
# logger.setLevel(logging.CRITICAL)

ch.setFormatter(formatter)
logger.addHandler(ch)

logger.debug('logger debug message')
logger.info('logger info message')
logger.warning('logger warning message')
logger.error('logger error message')
logger.critical('logger critical message')

輸出結果:
2018-11-13 23:40:13,829 - root - WARNING - logger warning message
2018-11-13 23:40:13,829 - root - ERROR - logger error message
2018-11-13 23:40:13,829 - root - CRITICAL - logger critical message

2)logger 日志級別設置為 CRITICAL,logger 設置為 ERROR

import logging

logger = logging.getLogger()
ch = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

ch.setLevel(logging.CRITICAL)
logger.setLevel(logging.ERROR)

ch.setFormatter(formatter)
logger.addHandler(ch)

logger.debug('logger debug message')
logger.info('logger info message')
logger.warning('logger warning message')
logger.error('logger error message')
logger.critical('logger critical message')

輸出結果:
2018-11-13 23:41:51,279 - root - CRITICAL - logger critical message

filter組件 的使用

filter組件用來過濾 logger 對象,一個 filter 可以直接添加到 logger對象上,也可以添加到 handler 對象上。
 
例如,定義一個filter: filter = logging.Filter('a.b'),當把這個 filter 添加到一個 handler 上,那么綁定了該 handler 的 多個 logger對象中,只有名字是 'a.b' 前綴的才能通過該 handler 輸出日志~
 
在 handler 上添加 filter:

import logging

logger1 = logging.getLogger('a.b.c')
logger2 = logging.getLogger('a.c')

# 定義一個 filter
filter = logging.Filter(name='a.b')

# 定義一個 handler
ch = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)

# 若兩個 logger對象 的日志級別相同,且都是用通過一個 handler,可以在這個 handler 上設置日志級別
ch.setLevel(logging.ERROR)

# 在 handler 上放置過濾器
ch.addFilter(filter)

logger1.addHandler(ch)
logger2.addHandler(ch)
logger1.error('logger1 error message')
logger2.error('logger2 error message')

輸出結果:
2018-11-15 21:58:33,409 - a.b.c - ERROR - logger1 error message

可以看到 logger2 被過濾,只有 logger1 輸出日志~
 
在 handler 上添加 filter:

import logging

logger1 = logging.getLogger('a.b.c')
logger2 = logging.getLogger('a.c')

# 定義一個 filter
filter = logging.Filter(name='a.b')

# 定義一個 handler
ch = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)

# 若兩個 logger對象 的日志級別相同,且都是用通過一個 handler,可以在這個 handler 上設置日志級別
ch.setLevel(logging.ERROR)

# 在 logger 上放置過濾器
logger1.addFilter(filter)
logger2.addFilter(filter)

logger1.addHandler(ch)
logger2.addHandler(ch)
logger1.error('logger1 error message')
logger2.error('logger2 error message')

輸出結果一致,即僅有 logger1 輸出日志。將 filter 添加到 logger 上,這個filter將直接作用于這個 logger,貌似這么意義不大,很少這樣使用

.................^_^

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI