python大型项目中的日志模块_Python中日志模块的使用
前言
程序和腳本往往是無人值守運(yùn)行的,一旦發(fā)生問題,就需要我們?nèi)プ匪莓?dāng)時(shí)的情況來定位問題的原因。
這便需要我們在程序和腳本中引入日志的功能。
相比于print信息,使用logging日志有以下優(yōu)點(diǎn)
可以記錄輸出日志的時(shí)間、文件、函數(shù)以及代碼行,甚至線程名和線程號
可以分等級記錄日志(調(diào)試級、信息級、警告級、錯誤級、嚴(yán)重錯誤級)
即可以實(shí)時(shí)輸出到屏幕,也可以輸出到文件
基本使用
Python中使用自帶的logging模塊輸出日志,logging模塊的主要組件為logger日志記錄器,如下圖。
基本使用如下
import logging
logging.debug('調(diào)試級別的日志')
logging.info('信息級別的日志')
logging.warning('警告級別的日志') # 或logging.warn('警告級別的日志')
logging.error('錯誤級別的日志')
logging.critical('嚴(yán)重錯誤級別的日志')
try:
1/0
except Exception as ex:
logging.exception(ex) # 錯誤級別的日志,顯示多行回溯信息
運(yùn)行結(jié)果為
WARNING:root:警告級別的日志
ERROR:root:錯誤級別的日志
CRITICAL:root:嚴(yán)重錯誤級別的日志
ERROR:root:division by zero
Traceback (most recent call last):
File "", line 9, in
1/0
ZeroDivisionError: division by zero
發(fā)現(xiàn)只顯示warning、error、critical的日志,這是因?yàn)閘ogging中的默認(rèn)日志記錄器(root logger)的level級別是logging.WARNING,即默認(rèn)只顯示警告級別以上的日志。
修改日志等級
我們可以使用logging.basicConfig來修改root logger的設(shè)置。
import logging
logging.basicConfig(level=logging.DEBUG) # 配置全局root logger
logging.debug('調(diào)試級別的日志')
logging.info('信息級別的日志')
logging.warning('警告級別的日志')
logging.error('錯誤級別的日志')
logging.critical('嚴(yán)重錯誤級別的日志')
再次運(yùn)行,發(fā)現(xiàn)所有的日志都可以輸出了。
level日志等級支持
logging.NOTSET: 未設(shè)置,輸出所有級別的日志
logging.DEBUG: 調(diào)試級別,輸出所有級別的日志
logging.INFO: 信息級別,輸出包含信息級別以上的日志
logging.WARNING: 警告級別,輸出包含警告級別的日志
logging.ERROR: 錯誤級別,輸出包含錯誤級別以上的日志
logging.CRITICAL: 嚴(yán)重錯誤級別,僅輸出嚴(yán)重錯誤日志
日志等級的關(guān)系為:CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET
修改日志格式
日志默認(rèn)的格式為WARNING:root:警告級別的日志,即等級:Logger名稱:輸出消息。我們也可以在logging.basicConfig中使用format參數(shù)來修改其輸出格式。
import logging
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s')
logging.debug('調(diào)試級別的日志')
logging.info('信息基本的日志')
logging.warning('警告級別的日志')
logging.error('錯誤級別的日志')
logging.critical('嚴(yán)重錯誤級別的日志')
運(yùn)行輸出如下:
2020-11-04 10:11:49,238 - DEBUG - 調(diào)試級別的日志
2020-11-04 10:11:49,238 - INFO - 信息基本的日志
2020-11-04 10:11:49,238 - WARNING - 警告級別的日志
2020-11-04 10:11:49,238 - ERROR - 錯誤級別的日志
2020-11-04 10:11:49,238 - CRITICAL - 嚴(yán)重錯誤級別的日志
format中使用%(變量名)s這樣的具名占位符,來輸出不同的信息,其他的字符則原樣顯示。
支持的變量如下:
%(levelno)s: 打印日志級別的數(shù)值
%(levelname)s: 打印日志級別名稱
%(pathname)s: 打印當(dāng)前執(zhí)行程序的路徑,其實(shí)就是sys.argv[0]
%(filename)s: 打印當(dāng)前執(zhí)行程序名
%(funcName)s: 打印日志的當(dāng)前函數(shù)
%(lineno)d: 打印日志的當(dāng)前行號(因?yàn)槭菙?shù)字,所以使用%d)
%(asctime)s: 打印日志的時(shí)間
%(thread)d: 打印線程ID
%(threadName)s: 打印線程名稱
%(process)d: 打印進(jìn)程ID
%(message)s: 打印日志信息
對于日期,我們可以使用datefmt來修改,比如,將上例中的logging.basicConfig修改為
...
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s',
datefmt='%Y年%m月%d日 %H:%M:%S')
...
輸出形式如下:
2020年11月04日 10:19:04 - DEBUG - 調(diào)試級別的日志
2020年11月04日 10:19:04 - INFO - 信息基本的日志
2020年11月04日 10:19:04 - WARNING - 警告級別的日志
2020年11月04日 10:19:04 - ERROR - 錯誤級別的日志
2020年11月04日 10:19:04 - CRITICAL - 嚴(yán)重錯誤級別的日志
輸出到文件
日志是默認(rèn)輸出的屏幕的,也可以通過logging.basicConfig中的filename將日志輸出到文件。
import logging
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s',
datefmt='%Y年%m月%d日 %H:%M:%S',
filename='run.log',
filemode='a'
)
logging.debug('調(diào)試級別的日志')
logging.info('信息基本的日志')
logging.warning('警告級別的日志')
logging.error('錯誤級別的日志')
logging.critical('嚴(yán)重錯誤級別的日志')
運(yùn)行后,日志將不會輸出到屏幕,轉(zhuǎn)而輸出到文件中,filemode支持'w'每次覆蓋和'a'追加模式。
自定義handlers
如果想即輸出到屏幕又輸出到文件,我們可以在logging.basicConfig的handlers參數(shù)中添加兩個(gè)不同的handler來實(shí)現(xiàn),logging.StreamHander()可以用于輸出到屏幕,logging.FileHandler()可以用于輸出到文件。
import logging
cli_handler = logging.StreamHandler() # 輸出到屏幕的日志處理器
file_handler = logging.FileHandler(filename='run.log', mode='a', encoding='utf-8') # 輸出到文件的日志處理器
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s',
datefmt='%Y年%m月%d日 %H:%M:%S',
handlers=[cli_handler, file_handler] # 添加兩個(gè)日志處理器
)
logging.debug('調(diào)試級別的日志')
logging.info('信息基本的日志')
logging.warning('警告級別的日志')
logging.error('錯誤級別的日志')
logging.critical('嚴(yán)重錯誤級別的日志')
這樣便可以即輸出到屏幕又輸出到文件了。
自定義Logger
使用logging.basicConfig是直接配置全局的root logger,會對項(xiàng)目中所有的模塊及三方包產(chǎn)生影響。
為了不影響其他模塊和三方包的日志輸出,我們可以使用自定義Logger,即日志記錄器,基本步驟為
使用logging.getLogger()新建一個(gè)logger對象,并配置期日志等級(總?cè)罩鹃_關(guān))
新建多個(gè)日志處理器,分別設(shè)置其格式和日志等級
將多個(gè)日志處理器添加到logger中
代碼如下
# 文件名: mylogger.py
import logging
def get_logger(name):
logger = logging.getLogger(name)
logger.setLevel(logging.DEBUG) # 設(shè)置總?cè)罩镜燃?/p>
format = logging.Formatter(fmt='%(asctime)s - %(levelname)s - %(message)s', datefmt='%Y年%m月%d日 %H:%M:%S') # 日志格式
cli_handler = logging.StreamHandler() # 輸出到屏幕的日志處理器
file_handler = logging.FileHandler(filename='run.log', mode='a', encoding='utf-8') # 輸出到文件的日志處理器
cli_handler.setFormatter(format) # 設(shè)置屏幕日志格式
file_handler.setFormatter(format) # 設(shè)置文件日志格式
cli_handler.setLevel(logging.INFO) # 設(shè)置屏幕日志等級, 可以大于日志記錄器設(shè)置的總?cè)罩镜燃?/p>
# file_hander.setLevel(logging.DEBUG) # 不設(shè)置默認(rèn)使用logger的等級
logger.handlers.clear() # 清空已有處理器, 避免繼承了其他logger的已有處理器
logger.addHandler(cli_handler) # 將屏幕日志處理器添加到logger
logger.addHandler(file_handler) # 將文件日志處理器添加到logger
return logger
使用方式為,導(dǎo)入本模塊的get_logger方法,使用logger代替logging打印各種信息。
from mylogger import get_logger
logger = get_logger('mylogger')
logger.debug('調(diào)試級別的日志')
logger.info('信息基本的日志')
logger.warning('警告級別的日志')
logger.error('錯誤級別的日志')
logger.critical('嚴(yán)重錯誤級別的日志')
注意:由于logger具有子模塊繼承性,在項(xiàng)目中多個(gè)地方使用get_logger生成不同的logger對象時(shí),有可能會繼承其他logger的處理器。建議項(xiàng)目中使用同一個(gè)logger。或者對日志記錄器使用單例模式。
在服務(wù)端項(xiàng)目中(如web項(xiàng)目),由于進(jìn)程是長久運(yùn)行,可以使用滾動日志處理器來分割日志文件。
總結(jié)
以上是生活随笔為你收集整理的python大型项目中的日志模块_Python中日志模块的使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。