您好,登錄后才能下訂單哦!
logging模塊是Python的一個標準庫模塊,開發(fā)過程中,可以通過該模塊,靈活的完成日志的記錄。
logging模塊提供了兩種記錄日志的方式:
????1)使用logging提供的模塊級別的函數(shù)(logging.basicConfig,logging.debug,logging.info...)
????2)使用logging模塊的組件(loggers,handlers,filters,formatters)
下面會分別介紹這兩種方式,這里建議使用第二種方式,使用 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
示例如下:
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模塊級別的函數(shù)記錄日志,無法實現(xiàn)將日志輸出到多個路徑下。這里logging模塊提供了4個組件,通過這些組件可實現(xiàn)將日志輸出到多個路徑下,且每個路徑下的日志格式可單獨配置~
組件名稱 | 功能描述 |
---|---|
Logger | 日志器,提供了應用程序可一直使用的接口 |
Handler | 將 logger 產(chǎn)生的日志發(fā)送到指定的路徑下(例如可以是終端,也可以是文件) |
Filter | 若有多個 Logger,可根據(jù)名稱過濾出指定的 Logger 來記錄日志 |
Formatter | 定義日志格式 |
使用組件記錄日志的大致步驟如下:
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組件用來過濾 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,貌似這么意義不大,很少這樣使用
.................^_^
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。