logging—記錄運行的日誌,python的logging模塊提供了標準的日誌接口,你能夠經過它存儲各類格式的日誌,logging的日誌能夠分爲 debug(), info(), warning(), error() and critical()
5個級別,專業的軟件都會有日誌級別python
看一下這幾個日誌級別分別表明什麼意思
web
Level | When it’s used |
---|---|
DEBUG |
調試,日常的日誌不會很詳細,調成debug會很詳細 |
INFO |
普通的記錄 |
WARNING |
沒有錯誤,擔心潛在的錯誤 |
ERROR |
出錯誤了 |
CRITICAL |
更高一級的錯誤 |
import logging logging.warning("user [alex] attempted wrong password more than 3 times") logging.critical("server is down")
輸出函數
WARNING:root:user [alex] attempted wrong password more than 3 times CRITICAL:root:server is down
其中root是默認以root用戶運行程序。
import logging logging.basicConfig(filename='log_text.log',level=logging.INFO) logging.debug('This message should go to the log file') logging.info('So should this') logging.warning('And this, too')
其中下面這句中的level=loggin.INFO意思是,把日誌紀錄級別設置爲INFO,也就是說,只有比日誌是INFO或比INFO級別更高的日誌纔會被紀錄到文件裏,在這個例子, 第一條日誌是不會被紀錄的,若是但願紀錄debug的日誌,那把日誌級別改爲DEBUG就好了。this
#打開log_text.log文件 INFO:root:So should this WARNING:root:And this, too
能夠看到只輸出了兩條錯誤,可是輸入了三條錯誤,因此就是說inf及之後的級別的日誌纔會被記錄。spa
若是再寫一個,會追加,而不是覆蓋線程
import logging logging.basicConfig(filename='log_text.log',level=logging.DEBUG) logging.debug('This message should go to the log file') logging.info('So should this') logging.warning('And this, too')
打開文件夾,會看到以下:debug
INFO:root:So should this
WARNING:root:And this, too
DEBUG:root:This message should go to the log file
INFO:root:So should this
WARNING:root:And this, too
那麼有什麼做用呢,若是有用戶攻擊你的電腦,假設你知道對方的IP地址,你再加上時間,就變成了有用的信息,也就是自定義日誌格式。import data 或 import time3d
import logging logging.basicConfig(filename='log_text.log',
level=logging.DEBUG,
format='%(asctime)s %(message)s',
datefmt='%m/%d/%Y %I:%M:%S %p')
logging.warning('is when this event was logged.')
打開文件調試
INFO:root:So should this WARNING:root:And this, too DEBUG:root:This message should go to the log file INFO:root:So should this WARNING:root:And this, too 05/22/2018 08:27:52 PM This message should go to the log file 05/22/2018 08:27:52 PM So should this 05/22/2018 08:27:52 PM And this, too
除了加時間,還能夠自定義一大堆格式,下表就是全部支持的格式日誌
%(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 | 用戶輸出的消息 |
舉例:
import logging logging.basicConfig(filename='log_text.log', level=logging.DEBUG, format='%(asctime)s:%(levelname)s:%(filename)s:%(funcName)s: %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p') def sayhi(): logging.error('from sayhi...') sayhi() logging.debug('This message should go to the log file') logging.info('So should this') logging.warning('And this, too')
05/22/2018 08:50:16 PM:ERROR:oneday.py:sayhi: from sayhi... 05/22/2018 08:50:16 PM:DEBUG:oneday.py:<module>: This message should go to the log file 05/22/2018 08:50:16 PM:INFO:oneday.py:<module>: So should this 05/22/2018 08:50:16 PM:WARNING:oneday.py:<module>: And this, too
上面是直接打在了屏幕上或者文件裏,下面既能夠搭載屏幕上,又會打在文件裏(也就是經過兩個方向輸入信息):
若是想同時把log打印在屏幕和文件日誌裏,就須要瞭解一點複雜的知識 了
Python 使用logging模塊記錄日誌涉及四個主要類(組件),使用官方文檔中的歸納最爲合適:
每一個Logger能夠附加多個Handler。接下來咱們就來介紹一些經常使用的Handler:
logging.handlers.RotatingFileHandler
這個Handler相似於上面的FileHandler,可是它能夠管理文件大小。當文件達到必定大小以後,它會自動將當前日誌文件更名,而後建立 一個新的同名日誌文件繼續輸出。好比日誌文件是chat.log。當chat.log達到指定的大小以後,RotatingFileHandler自動把 文件更名爲chat.log.1。不過,若是chat.log.1已經存在,會先把chat.log.1重命名爲chat.log.2。。。最後從新建立 chat.log,繼續輸出日誌信息。它的函數是:
RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]])
其中filename和mode兩個參數和FileHandler同樣。
logging.handlers.TimedRotatingFileHandler
這個Handler和RotatingFileHandler相似,不過,它沒有經過判斷文件大小來決定什麼時候從新建立日誌文件,而是間隔必定時間就 自動建立新的日誌文件。重命名的過程與RotatingFileHandler相似,不過新的文件不是附加數字,而是當前時間。它的函數是:
TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]])
其中filename參數和backupCount參數和RotatingFileHandler具備相同的意義。
interval
是時間間隔。
when
參數是一個字符串。表示時間間隔的單位,不區分大小寫。它有如下取值:
日誌的formatter是個獨立的組件,能夠跟handler組合
fh = logging.FileHandler("access.log") formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') fh.setFormatter(formatter) #把formmater綁定到fh上
import logging #1. 生成logger對象 logger = logging.getLogger('web') logger.setLevel(logging.INFO)#設置訪問級別 #2. 生成handle對象 ch = logging.StreamHandler() fh = logging.FileHandler('web.log') #2.1 把handle對象綁到logger logger.addHandler(ch) logger.addHandler(fh) #3. 生成formatter 對象 #3.1 把formatter對象幫綁到handle對象 file_matter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') console_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(lineno)d - %(message)s') ch.setFormatter(console_formatter) fh.setFormatter(file_matter) logger.debug('text.log')
文件和屏幕會有顯示:
但若是像下面這樣
import logging #1. 生成logger對象 logger = logging.getLogger('web') logger.setLevel(logging.INFO)#設置訪問級別 #2. 生成handle對象 ch = logging.StreamHandler() ch.setLevel(logging.DEBUG)# 對屏幕設置日誌級別 fh = logging.FileHandler('web.log') fh .setLevel(logging.WARNING) # 對文件設置級別 #2.1 把handle對象綁到logger logger.addHandler(ch) logger.addHandler(fh) #3. 生成formatter 對象 #3.1 把formatter對象幫綁到handle對象 file_matter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') console_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(lineno)d - %(message)s') ch.setFormatter(console_formatter) fh.setFormatter(file_matter) logger.info('text.log') logger.debug('text log2') #console : DEBUG #global : INFO #file : Warning
咱們發現只有info會再屏幕和文件顯示
日誌過濾和日誌文件自動截取
若是你想對日誌內容進行過濾,就可自定義一個filter
class IgnoreBackupLogFilter(logging.Filter): """忽略帶db backup 的日誌""" def filter(self, record): #固定寫法 return "db backup" not in record.getMessage()
注意filter函數會返加True or False,logger根據此值決定是否輸出此日誌
而後把這個filter添加到logger中
logger.addFilter(IgnoreBackupLogFilter())
下面的日誌就會把符合filter條件的過濾掉
logger.debug("test ....") logger.info("test info ....") logger.warning("start to run db backup job ....") logger.error("test error ....")
一個同時輸出到屏幕、文件、帶filter的完成例子