1. 程式人生 > >python常用模組——logging

python常用模組——logging

日誌模組 logging

預設情況下Python的logging模組的日誌級別是warning,預設輸出到標準輸出stdout 預設的日誌格式為 日誌級別:Logger名稱:使用者輸出訊息; 設定logging的預設格式及輸出位置使用basicConfig方法。

一、 logging模組的常用方法

1. basicConfig(**kwargs)

    配置日誌基本配置;引數可以是如下:  
        filename:用指定的檔名建立FiledHandler(後邊會具體講解handler的概念),這樣日誌會被儲存在指定的檔案中。
        filemode:檔案開啟方式,在指定了filename時使用這個引數,預設值為“a”還可指定為“w”,一般預設。
        format:指定handler使用的日誌顯示格式。 
        datefmt:指定日期時間格式。 
        level:設定rootlogger(後邊會講解具體概念)的日誌級別;預設是warnning
        stream:用指定的stream建立StreamHandler。可以指定輸出到sys.stderr,sys.stdout或者檔案(f=open('test.log','w')),預設為sys.stderr。若同時列出了filename和stream兩個引數,則stream引數會被忽略。
        style     這個再補充吧
        handlers  如果指定的話,這應該是一個已經建立的程式,將其新增到root handler。在沒有格式化指定列表中的任何處理程式將被分配在這個函式建立格式化程式。
    format引數中可能用到的格式化串:
        %(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使用者輸出的訊息  

2. disable(level)

    關閉指定級別及以下級別的日誌;

3. logging.debug()

    記錄debug級別的日誌;

4. logging.info()

    記錄info級別日誌;

5. logging.warning()

    記錄warning級別日誌;

6. logging.error()

    記錄error級別日誌;

7. logging.critical()

    記錄critical級別日誌; 

8. logging.getLogger()

模組級別的函式logging.getLogger('name'),返回一個logger物件,如果沒有指定名字將返回root logger;
例如: logging.getLogger('mylogger')

9. logging.FileHandler('/tmp/test.log')

建立一個handler,用於寫入日誌檔案;

10. logging.StreamHandler()

建立一個handler,用於輸出到控制檯;

二、 案例

案例一: 輸出日誌在檔案和終端

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import logging  

#預設輸出為stdout
logging.debug('debug message')  
logging.info('info message')  
logging.warning('warning message')  
logging.error('error message')  
logging.critical('critical message')  

#設定預設輸出
logging.basicConfig(level=logging.DEBUG,  
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',  
                    datefmt='%a, %d %b %Y %H:%M:%S',  
                    filename='/tmp/test.log',  
                    filemode='w')  

#再次列印日誌,日誌輸出為檔案
logging.debug('debug message')  
logging.info('info message')  
logging.warning('warning message')  
logging.error('error message')  
logging.critical('critical message')

案例二:同時輸出在多個位置

如果這個案例看不懂,先看下面第三部分;

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import logging

logger = logging.getLogger()

# 建立一個handler fh,用於寫入日誌檔案
fh = logging.FileHandler('test.log')

# 再建立一個handler ch,用於輸出到控制檯
ch = logging.StreamHandler()

formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

fh.setFormatter(formatter)
ch.setFormatter(formatter)

logger.addHandler(fh)              #logger物件可以新增多個fh和ch物件
logger.addHandler(ch)

logger.debug('logger debug message')
logger.info('logger info message')
logger.warning('logger warning message')
logger.error('logger error message')
logger.critical('logger critical message')

可以看到,同時輸出在stdout和檔案;

案例三:

import logging

logger1=logging.getLogger('mylogger')
logger2=logging.getLogger('mylogger')

print(logger1)              # 
print(logger2)              # 

logger1.setLevel('DEBUG')

print(logger1)              # 
print(logger2)              # 

上面案例可以發現,name和logger例項是一一對應的。即使賦給了logger1/logger2,更改其中一個,另一個也會跟著改變;

三、 日誌模組解析

  • logging.basicConfig()

    用預設日誌格式(Formatter)為日誌系統建立一個預設的流處理器(StreamHandler),設定基礎配置(如日誌級別等)並加到root logger(根Logger)中;
    
  • logging.getLogger()

    返回一個logger物件,如果沒有指定名字將返回root logger;
    另外,建立的logger都是root logger的“孩子”;這裡mylogger屬於root logger的子孫,繼承root logger的屬性(日誌級別、Handler、Filter設定),除非設定了mylogger的屬性。
    可以通過Logger.setLevel(lel)、Logger.addHandler(hdlr)、Logger.removeHandler(hdlr)、Logger.addFilter(filt)、Logger.removeFilter(filt) 來設定mylogger的日誌級別、Handler、Filter。
    
  • logging元件

    Logger:  記錄器,暴露了應用程式程式碼能直接使用的介面。
    Handler: 處理器,將(記錄器產生的)日誌記錄傳送至合適的目的地。
    Filter: 過濾器,提供了更好的粒度控制,它可以決定輸出哪些日誌記錄。
    Formatter: 格式化器,指明瞭最終輸出中日誌記錄的格式。
    

1. logger

Logger是一個樹形層級結構,輸出資訊之前都要獲得一個Logger(如果沒有顯示的獲取則自動建立並使用root Logger)。可以通過Logger.setLevel(level)或logging.basicConfig()指定最低的日誌級別。

Logger可以包含一個或多個Handler和Filter,即Logger與Handler或Fitler是一對多的關係; 一個Logger例項可以新增多個Handler,一個Handler可以新增多個格式化器或多個過濾器,而且日誌級別將會繼承。

建立方法:
     logger = logging.getLogger(logger_name)

建立Logger例項後,可以使用以下方法進行日誌級別設定,增加處理器Handler:

  • logger.setLevel(logging.ERROR)      # 設定日誌級別為ERROR,即只有日誌級別大於等於ERROR的日誌才會輸出
  • logger.addHandler(handler_name)      # 為Logger例項增加一個處理器
  • logger.removeHandler(handler_name)    # 為Logger例項刪除一個處理器

2. handler

Handler處理器型別有很多種,比較常用的有三個,StreamHandler,FileHandler,NullHandler,詳情可以檢視官網。

建立handler:
    logging.FileHandler('/tmp/test.log',mode='a', encoding=None, delay=False)
    logging.StreamHandler() 
    NullHandler類位於核心logging包,不做任何的格式化或者輸出。本質上它是個“什麼都不做”的handler,由庫開發者使用。

建立StreamHandler之後,可以通過使用以下方法設定日誌級別,設定格式化器Formatter,增加或刪除過濾器Filter:

  • ch.setLevel(logging.WARN)       # 指定日誌級別,低於WARN級別的日誌將被忽略
  • ch.setFormatter(formatter_name)    # 設定一個格式化器formatter
  • ch.addFilter(filter_name)        # 增加一個過濾器,可以增加多個
  • ch.removeFilter(filter_name)      # 刪除一個過濾器

3. formatter

使用Formatter物件設定日誌資訊最後的規則、結構和內容,預設的時間格式為%Y-%m-%d %H:%M:%S。

建立方法:
   formatter = logging.Formatter(fmt=None, datefmt=None)

其中,fmt是訊息的格式化字串,datefmt是日期字串。如果不指明fmt,將使用'%(message)s'。如果不指明datefmt,將使用ISO8601日期格式。

4. Filer

日誌過濾,只有滿足過濾規則的日誌才會輸出。

建立方法: 
    filter = logging.Filter(name='')

例如:

filter = logging.Filter('mylogger')     # 使用該filter的handler將只記錄mylogger開頭的日誌; 
fh.addFilter(filter)
ch.addFilter(filter)

更多:https://docs.python.org/3.6/library/logging.html