python的logging模塊是用來設置日誌的,是python的標準模塊。html
python模塊分析之random(一)python
DEBUG:優先級10,記錄調試的詳細信息,只在調試時開啓;ide
INFO:優先級20,記錄普通的消息,包括錯誤和警告等等;函數
WARNING:優先級30,記錄相關的警告信息;測試
ERROR:優先級40,記錄錯誤信息,程序崩潰;
CRITICAL:優先級50,記錄錯誤信息;
若是不設置級別的話,默認爲warning,系統記錄設置的日誌級別優先級以上的日誌信息。
查看logging的源碼,可知主要有四個類實現功能;
Loggers:提供應用程序直接使用的接口,如相關的配置設置;
Handlers:將Loggers產生的日誌傳到指定位置,設置日誌保存的位置;
Filters:對輸出日誌進行過濾操做;
Formatters:控制日誌的輸出格式;
Formatter對象定義了日誌的輸出格式,有多種可選參數。
%(name)s Logger的名字 %(levelno)s 數字形式的日誌級別 %(levelname)s 文本形式的日誌級別 %(pathname)s 調用日誌輸出函數的模塊的完整路徑名,可能沒有 %(filename)s 調用日誌輸出函數的模塊的文件名 %(module)s 調用日誌輸出函數的模塊名| %(funcName)s 調用日誌輸出函數的函數名| %(lineno)d 調用日誌輸出函數的語句所在的代碼行 %(created)f 當前時間,用UNIX標準的表示時間的浮點數表示| %(relativeCreated)d 輸出日誌信息時的,自Logger建立以來的毫秒數| %(asctime)s 字符串形式的當前時間。默認格式是「2003-07-08 16:49:45,896」。逗號後面的是毫秒 %(thread)d 線程ID。可能沒有 %(threadName)s 線程名。可能沒有 %(process)d 進程ID。可能沒有 %(message)s 用戶輸出的消息 # 定義一個輸出格式的對象 formatter = logging.Formatter('%(asctime)s %(levelname)s: %(message)s',datefmt='%Y-%m-%d %H:%M:%S', style='%') # Formatter參數: fmt:定義輸出的日誌信息的格式; datefmt:定義時間信息的格式,默認爲'%Y-%m-%d %H:%M:%S'; style:定義格式化輸出的佔位符,默認是%(name)格式,可選{}或$格式
日誌處理器用來處理日誌的具體流向,是輸出到文件中仍是到標準輸出等,它經過設置Formatter控制輸出格式,添加filters過濾日誌;
StreamHandler:用於向控制檯打印日誌;
FileHandler:用於向日志文件打印日誌;
RotatingHandler:logging.handlers.RotatingHandler;日誌回滾方式,支持日誌文件最大數量和日誌文件回滾 TimeRotatingHandler:logging.handlers.TimeRotatingHandler;日誌回滾方式,在必定時間區域內回滾日誌文件 SocketHandler:logging.handlers.SocketHandler;遠程輸出日誌到TCP/IP sockets DatagramHandler:logging.handlers.DatagramHandler;遠程輸出日誌到UDP sockets SMTPHandler:logging.handlers.SMTPHandler;遠程輸出日誌到郵件地址 SysLogHandler:logging.handlers.SysLogHandler;日誌輸出到syslog NTEventLogHandler:logging.handlers.NTEventLogHandler;遠程輸出日誌到Windows NT/2000/XP的事件日誌 MemoryHandler:logging.handlers.MemoryHandler;日誌輸出到內存中的指定buffer HTTPHandler:logging.handlers.HTTPHandler;經過"GET"或者"POST"遠程輸出到HTTP服務器
from logging import Handler handler = Handler() # 全部上述處理器的父類 print(handler.level) # 處理日誌的等級 print(handler.name) # 處理日誌的名字 print(handler.filters) # 處理器的日誌過濾器 print(handler.formatter) # 日誌的格式 handler.get_name() handler.set_name('') handler.createLock() # 建立線程鎖 handler.acquire() # 獲取線程鎖 handler.release() # 釋放線程鎖 handler.setLevel('info') # 設置日誌處理器的記錄級別 handler.setFormatter(fmt='') # 設置日誌的輸出格式 handler.addFilter('') # 往處理器中添加過濾器 handler.removeFilter('') # 往處理器中移除過濾器 handler.emit('') # 日誌記錄的處理邏輯,由子類實現
Logger管理着全部記錄日誌的方法。
logger = getLogger(__name__) # 返回一個Logger實例 # logger = getLogger('root') # 以'root'爲名字的日誌對象在Logger對象中只有一個實例 # 若是是想調用以'root'爲名字的日誌對象輸出日誌,能夠直接導入 from logging import error, debug, warning, info, fatal, critical print(logger.root) # 獲取根日誌對象 print(logger.manager) # 獲取manager print(logger.name) # 日誌對象的名字 print(logger.level) # 日誌記錄水平 print(logger.filters) # 日誌過濾器列表 print(logger.handlers) # 日誌處理器列表 print(logger.disabled) logger.setLevel('info') # 設置日誌記錄水平 logger.info('this is %s', 'info', exc_info=1) # 輸出日誌信息,格式化輸出 logger.warning('') # 記錄warning信息 logger.error('') # 記錄error信息 logger.exception('') # 等價於logger.error('', exc_info=1) logger.debug('') # 記錄debug信息 logger.critical('') # 記錄critical信息 logger.log('info','') # 直接指定級別 logger.addHandler('') # 添加處理器 logger.removeHandler('') # 移除處理器 logger.hasHandlers() # 判斷是否有處理器
import logging import sys def get_logger(appname): # 獲取logger實例,若是參數爲空則返回root logger logger = logging.getLogger(appname) # 建立日誌輸出格式 formatter = logging.Formatter('%(asctime)s %(levelname)s: %(message)s') # 設置文件處理器,加載處理格式 file_handler = logging.FileHandler("test.log") # 指定輸出的文件路徑 file_handler.setFormatter(formatter) # 控制檯日誌 console_handler = logging.StreamHandler(sys.stdout) console_handler.formatter = formatter # 爲logger添加的日誌處理器 logger.addHandler(file_handler) logger.addHandler(console_handler) # 指定日誌的最低輸出級別,默認爲WARN級別 logger.setLevel(logging.INFO) if __name__ == "__main__": logger = get_logger('test') logger.debug('this is debug info') logger.info('this is information') logger.warn('this is warning message') logger.error('this is error message') logger.fatal('this is fatal message, it is same as logger.critical') logger.critical('this is critical message')
記錄日誌經過調用logger.debug等方法;
首先判斷本條記錄的日誌級別是否大於設置的級別,若是不是,直接pass,再也不執行;
將日誌信息當作參數建立一個LogRecord日誌記錄對象;
將LogRecord對象通過logger過濾器過濾,若是被過濾掉則pass;
日誌記錄對象被Handler處理器的過濾器過濾;
判斷本條記錄的日誌級別是否大於Handler處理器設置的級別,若是不是,直接pass,再也不執行,最後調用處理器的emit方法處理日誌記錄;
# logging.conf [loggers] # 定義日誌的對象名稱是什麼,注意必須定義root,不然報錯。 keys=root,main [handlers] # 定義處理器的名稱是什麼,能夠有多個,用逗號隔開 keys=consoleHandler [formatters] # 定義輸出格式對象的名稱,能夠有多個,用逗號隔開 keys=simpleFormatter [logger_root] # 配置root對象的日誌記錄級別和使用的處理器 level=INFO handlers=consoleHandler [logger_main] # 配置main對象的日誌記錄級別和使用的處理器,qualname值得就是日誌對象的名字 level=INFO handlers=consoleHandler qualname=main propagate=0 # logger對象把日誌記錄傳遞給全部相關的handler的時候,會(逐級向上)尋找這個logger和它全部的父logger的所有handler,propagate=1表示會繼續向上搜尋;propagate=0表示中止搜尋,這個參數涉及重複打印的坑。 [handler_consoleHandler] # 配置處理器consoleHandler class=StreamHandler level=WARNING formatter=simpleFormatter args=(sys.stdout,) [formatter_simpleFormatter] # 配置輸出格式過濾器simpleFormatter format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
字典形式配置功能更增強大,也更加靈活。經過dictConfig函數,咱們能夠將其餘格式的配置文件先轉化成字典,如json、YAML等。
import yaml from logging.config import dictConfig import os filename = os.path.dirname(os.path.abspath(__file__)) with open(filename + '\logging.yml', 'r') as f: log = yaml.load(f.read()) dictConfig(log)
# logging.yaml version: 1 formatters: simple: format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s' handlers: console: class: logging.StreamHandler level: DEBUG formatter: simple stream: ext://sys.stdout console_err: class: logging.StreamHandler level: DEBUG formatter: simple stream: ext://sys.stderr loggers: simpleExample: level: DEBUG handlers: [console] propagate: no root: level: DEBUG handlers: [console_err]
logging.getLogger(appname),同一個appname獲取到的logger對象是同一個,同時appname.name命名的logger繼承了appname的全部的屬性,能夠不用從新配置logger。
try: raise except: logger.error('this is error message',exc_info = True) # 或 logger.exception("Failed to open sklearn.txt from logger.exception") # 設置exc_info爲True後,會自動將錯誤的信息也發送到日誌中; # 直接使用exception實現同樣的功能。
import logging.config import logging import time logging.config.fileConfig("logging.conf") logger = logging.getLogger("test.listen") t = logging.config.listen(9999) t.setDaemon(True) t.start() # 啓動監聽服務器