python—模塊-logging

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將(logger建立的)日誌記錄發送到合適的目的輸出;
  • filter提供了細度設備來決定輸出哪條日誌記錄;
  • formatter決定日誌記錄的最終輸出格式。

他們之間的關係是這樣的

 

每一個Logger能夠附加多個Handler。接下來咱們就來介紹一些經常使用的Handler:

  1. logging.StreamHandler 使用這個Handler能夠向相似與sys.stdout或者sys.stderr的任何文件對象(file object)輸出信息。
  2. logging.FileHandler 和StreamHandler 相似,用於向一個文件輸出日誌信息。不過FileHandler會幫你打開這個文件
  3. 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同樣。

    • maxBytes用於指定日誌文件的最大文件大小。若是maxBytes爲0,意味着日誌文件能夠無限大,這時上面描述的重命名過程就不會發生。
    • backupCount用於指定保留的備份文件的個數。好比,若是指定爲2,當上面描述的重命名過程發生時,原有的chat.log.2並不會被改名,而是被刪除。
  4. logging.handlers.TimedRotatingFileHandler

    這個Handler和RotatingFileHandler相似,不過,它沒有經過判斷文件大小來決定什麼時候從新建立日誌文件,而是間隔必定時間就 自動建立新的日誌文件。重命名的過程與RotatingFileHandler相似,不過新的文件不是附加數字,而是當前時間。它的函數是:

    TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]])

    其中filename參數和backupCount參數和RotatingFileHandler具備相同的意義。

    interval是時間間隔。

    when參數是一個字符串。表示時間間隔的單位,不區分大小寫。它有如下取值:

    • S 秒
    • M 分
    • H 小時
    • D 天
    • W 每星期(interval==0時表明星期一)
    • midnight 天天凌晨

formatter 組件

日誌的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 組件

若是你想對日誌內容進行過濾,就可自定義一個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的完成例子

相關文章
相關標籤/搜索