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