logging模塊

  python的logging模塊提供了標準的日誌接口,你能夠經過它存儲各類格式的日誌。python

logging的日誌分爲debug()、info()、warning()、error()、critical()五個級別
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
"""
日誌寫入文件
import logging

logging.basicConfig(filename='log_test.log', level=logging.INFO)
logging.debug("This message should go to the log file")
logging.info("so should this")
logging.warning("And this,too")
"""
log_test.log中僅寫入了warning和info信息
"""

  在basicConfig中,filename指定了文件路徑,level=logging.INFO是把日誌記錄設置爲INFO,只輸入INFO或者比INFO級別更高的日誌(日誌級別過濾)。web

自定義日誌格式
import logging

logging.basicConfig(filename='log_test.log',
                    level=logging.DEBUG,
                    format='%(asctime)s-%(name)s-%(filename)s-%(funcName)s-%(lineno)d-%(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")

  執行會生成log_test.log文件,文件內容以下:網絡

04/18/2018 03:19:00 PM-root-logging_module.py-sayhi-40-from sayhi....
04/18/2018 03:19:00 PM-root-logging_module.py-<module>-42-This message should go to the log file
04/18/2018 03:19:00 PM-root-logging_module.py-<module>-43-so should this
04/18/2018 03:19:00 PM-root-logging_module.py-<module>-44-And this,too

  除了能夠在日誌格式上加上時間以外,還能夠自定義不少格式:函數

參數格式介紹:
%(levelno)s     # 打印數字形式的日誌級別(10對應debug,20對應info,30對應warning)
%(levelname)s   # 打印文本形式的日誌級別 %(pathname)s    # 調用日誌輸出函數的模塊的完整路徑名
%(filename)s    # 調用日誌輸出函數的模塊的文件名

%(module)s      # 調用日誌輸出函數的模塊名
%(funcName)s    # 調用日誌輸出函數的函數名
%(lineNo)d      # 調用日誌輸出函數的語句所在的代碼行(44)
%(created)f     # 當前時間,用UNIX標準的表示是時間(通常時間用datafmt便可)
%(relaticeCreated)d    # 輸出日誌信息時,自Logger建立以來的毫秒數

%(asctime)s     # 字符串形式的當前時間,默認格式"2003-08-08 16:32:21,878",逗號後爲毫秒數

%(thread)d      # 線程ID  
%(threadName)s  # 線程名
%(process)d     # 進程ID

%(message)s     # 用戶輸出的消息

 

日誌同時輸出到屏幕和文件

Python使用logging模塊記錄日誌涉及四個主要類:
  一、logger提供了應用程序能夠直接使用的接口;
  二、handler將(logger建立的)日誌記錄發送到合適的目的輸出;
  三、filter對記錄的日誌過濾決定哪條日誌輸出;
  四、formatter決定日誌記錄的最終輸出格式。
工具

這四個類之間的關係:

  首先在輸出信息以前獲取一個logger對象,用getLogger()方法指定文件名;其次利用StreamHandler()輸送到屏幕,利用FileHandler('文件名')輸送到文件;再利用addHandler()方法將handler對象加進Logger對象中。接着能夠生成Formatter對象,設置文件輸出格式,利用setFormatter()方法將輸出格式綁定到hander對象上。測試

  最後由Filters對象對日誌進行過濾,通常與Logger進行關聯,若是屏幕和文件的日誌過濾機制不一樣,能夠與handler進行關聯。ui

Logger組件

  每一個程序在輸出信息以前都要得到一個Logger。Logger一般對應了程序的模塊名,好比聊天工具的圖形界面模塊、核心模塊能夠這樣得到它的Logger:this

LOG = logging.getLogger("chat.gui")  # 圖形界面模塊
LOG2 = logging.getLogger("chat.kernal") # 核心模塊

  指定日誌級別、綁定或刪除handler和filters:spa

# 指定最低的日誌級別,低於lel的級別將被忽略。debug是最低的內置級別,critical爲最高
logging.Logger.setLevel() # 低於指定級別將被忽略

# 添加或刪除指定的filter
logging.Logger.addFilter()
logging.Logger.removeFilter()

# 添加或刪除指定的handler
logging.Logger.addHandler()
logging.Logger.removeHandler()

  Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical():能夠設置的日誌級別線程

handler模塊

  handler對象負責發送相關信息到指定的目的地(控制檯、文件、網絡):

logging.Handler.setLevel()  # 指定被處理信息級別
logging.Handler.setFormatter()  # 給這個handler選擇一個格式
logging.Handler.addFilter() # 新增一個filter對象
logging.Handler.removeFilter() # 刪除一個filter對象

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

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

 

filter組件

  對日誌過濾,可自定義一個filter,通用格式以下:(注意filter函數會返加True or False,logger根據此值決定是否輸出此日誌

class IgnoreBackupLogFilter(logging.Filter):
    """忽略帶db backup 的日誌"""
    def filter(self, record): #固定寫法
        return   "db backup" not in record.getMessage()

  而後將這個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的例子

 

import logging


class IgnoreBackupLogFilter(logging.Filter):
    """忽略帶db backup 的日誌"""

    def filter(self, record):  # 固定寫法
        return "db backup" not in record.getMessage()  # 字段不在日誌消息內


# 生成logger對象
logger = logging.getLogger("web")
logger.setLevel(logging.DEBUG)  # 不設置日誌級別,默認日誌級別是warning
# 把filter對象添加到logger中 logger.addFilter(IgnoreBackupLogFilter()) # 生成handler對象 ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) # 屏幕debug級別 fh = logging.FileHandler("web.log") fh.setLevel(logging.WARNING) # 文件設置WARNING級別 # 把handler對象綁定到logger對象 logger.addHandler(ch) logger.addHandler(fh) # 生成formatter對象 file_formater = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') console_formater = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(lineno)d - %(message)s') # 把formatter對象綁定hander對象 ch.setFormatter(console_formater) fh.setFormatter(file_formater) logger.debug("test_log") logger.warning("test_log_2") logger.debug("test log db backup 3") # filter測試,不記錄這條日誌 """ 在全局日誌級別:info (不設置默認級別是warning,通常能夠把全局設低把其餘級別設高) 屏幕日誌級別:debug 文件日誌級別:warning 這種狀況下,屏幕日誌級別不生效,依然按照全局日誌級別僅輸出一條: 2018-03-03 16:27:28,508 - web - WARNING - 23 - test_log_2 全局設置爲DEBUG後,console_handler設置爲INFO,若輸出的日誌級別爲DEBUG,則不會再屏幕顯示 """

  能夠看到上述程序設置屏幕日誌級別爲debug, 文件日誌級別爲warning,同時過濾信息爲「db backup」。屏幕輸出和web.log文件日誌以下所示:

# 控制檯日誌
2018-04-18 16:34:21,376 - web - DEBUG - 32 - test_log
2018-04-18 16:34:21,376 - web - WARNING - 33 - test_log_2

# web.log日誌
2018-04-18 16:34:21,376 - web - WARNING - test_log_2

 

根據文件大小截斷日誌

  函數示例:logging.RotatingFileHandler(filename[, mode[, maxBytes[, backupCount]]]),當文件達到必定大小後,會自動將當前日誌文件更名,而後建立一個新的同名的日誌文件繼續輸出。

import logging
from logging import handlers


class IgnoreBackupLogFilter(logging.Filter):
    """忽略帶db backup 的日誌"""

    def filter(self, record):  # 固定寫法
        return "db backup" not in record.getMessage()  # 字段不在日誌消息內


# 生成logger對象
logger = logging.getLogger("web")
logger.setLevel(logging.DEBUG)  # 不設置日誌級別,默認日誌級別是warning

# 把filter對象添加到logger中
logger.addFilter(IgnoreBackupLogFilter())

# 生成handler對象
ch = logging.StreamHandler()
# ch.setLevel(logging.DEBUG)  # 屏幕debug級別

# 生成RotatingFileHandler對象
# fh = logging.FileHandler("web.log")
fh = handlers.RotatingFileHandler("web_jd.log", maxBytes=10, backupCount=3)   # 限制文件大小,日誌截斷
# fh.setLevel(logging.WARNING)  # 文件設置WARNING級別

# 把handler對象綁定到logger對象
logger.addHandler(ch)
logger.addHandler(fh)

# 生成formatter對象
file_formater = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
console_formater = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(lineno)d - %(message)s')

# 把formatter對象綁定hander對象
ch.setFormatter(console_formater)
fh.setFormatter(file_formater)

logger.debug("test_log")
logger.warning("test_log_2")
logger.debug("test log db backup 3")
"""
輸出web_jd.log.1  web_jd.log.2這三個文件
web_jd.log:
2018-03-03 16:54:32,307 - web - WARNING - test_log_2
web_jd.log.1:
2018-03-03 16:54:32,307 - web - DEBUG - test_log
web_jd.log.2:
2018-03-03 16:53:38,900 - web - DEBUG - test_log
2018-03-03 16:53:38,901 - web - WARNING - test_log_2
"""

 

根據時間截斷日誌

 handlers.TimedRotatingFileHandler()方法

import logging
from logging import handlers


class IgnoreBackupLogFilter(logging.Filter):
    """忽略帶db backup 的日誌"""

    def filter(self, record):  # 固定寫法
        return "db backup" not in record.getMessage()  # 字段不在日誌消息內


# 生成logger對象
logger = logging.getLogger("web")
logger.setLevel(logging.DEBUG)  # 不設置日誌級別,默認日誌級別是warning

# 把filter對象添加到logger中
logger.addFilter(IgnoreBackupLogFilter())

# 生成handler對象
ch = logging.StreamHandler()
# ch.setLevel(logging.DEBUG)  # 屏幕debug級別
# fh = logging.FileHandler("web.log")
fh = handlers.TimedRotatingFileHandler("web_jd.log", when="S", interval=5, backupCount=3)
# fh.setLevel(logging.WARNING)  # 文件設置WARNING級別
# 把handler對象綁定到logger對象
logger.addHandler(ch)
logger.addHandler(fh)

# 生成formatter對象
file_formater = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
console_formater = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(lineno)d - %(message)s')
# 把formatter對象綁定hander對象
ch.setFormatter(console_formater)
fh.setFormatter(file_formater)

logger.debug("test_log")
logger.warning("test_log_2")
logger.debug("test log db backup 3")
"""兩次執行生成兩個文件
文件web_jd.log.2018-04-18_19-29-22
2018-04-18 19:29:22,013 - web - WARNING - test_log_2
文件web_jd.log.2018-04-18_22-49-38
2018-04-18 22:49:38,467 - web - DEBUG - test_log
2018-04-18 22:49:38,469 - web - WARNING - test_log_2
"""
相關文章
相關標籤/搜索