【Python】 模組之logging

楊奇龍發表於2016-06-14
前言
   Python 的logging 模組定義的函式和類為應用程式和庫實現了一個靈活的事件日誌系統。該模組提供多種日誌級別並且支援多種記錄日誌的方式比如 終端,檔案等等。在編寫一個軟體系統的時候 ,使用日誌系統十分有必要 記錄函式的執行過程和異常報錯資訊。本文算是一個學習筆記,對於跨檔案引用的初學者有一定幫助。
一 入門 
talk is cheap ,show me the code.
1 例子 logt.py
  1. #!/usr/bin/python
  2. # -*- coding:utf-8 -*-
  3. import logging
  4. logging.debug('this is a debug message')
  5. logging.info('this is a info message')
  6. logging.warn('this is a warn message')
  7. logging.error('this is a error message')
  8. logging.critical('this is a critical message')
執行該指令碼
  1. root@rac4:~# >python logt.py
  2. WARNING:root:this is a warn message
  3. ERROR:root:this is a error message
  4. CRITICAL:root:this is a critical message
看到這個輸出 ,有人可能會有疑問 為什麼 logging.debug()和logging.info()沒有輸出內容? 恩,這個是個好問題,莫慌,且看下文分析。
2. logging 的日誌級別
logging 提供了完整的日誌體系,支援五種日誌級別以便記錄程式的執行過程。
DEBUG         詳細資訊,典型地除錯問題的時候會使用。
INFO             證明事情按預期工作。
WARNING    表明發生了一些意外,或者不久的將來會發生問題(如‘磁碟滿了’)。軟體還是在正常工作。
ERROR         由於更嚴重的問題,軟體已不能執行一些功能了。
CRITICAL     嚴重錯誤,表明軟體已不能繼續執行了。
以上五種日誌級別從低到高分別是:DEBUG < INFO < WARNING < ERROR < CRITICAL 。預設的是WARNING,只有日誌級別高於WARNING的日誌資訊才會輸出,而輸出有兩種方式 一種輸出控制檯,也是預設的方式,另一種是記錄到檔案中,如日誌檔案。
3 logging的配置
python提供了多種配置方式控制日誌的顯示格式,內容,目的等。如上述例子中的日誌輸出“WARNING:root:this is awarn message”。
顯式建立記錄器Logger、處理器Handler和格式化器Formatter,並進行相關設定;
透過簡單方式進行配置,使用basicConfig()函式直接進行配置;
透過配置檔案進行配置,使用fileConfig()函式讀取配置檔案;
透過配置字典進行配置,使用dictConfig()函式讀取配置資訊;
本文使用方式作為例子。
basicConfig()支援下列關鍵字引數。
格式    描述
filename    建立一個FileHandler,使用指定的檔名,而不是使用StreamHandler。
filemode    如果指明瞭檔名,指明開啟檔案的模式(如果沒有指明filemode,預設為'a',即append方式)。
format        handler使用指明的格式化字串。詳細的請參考
datefmt       使用指明的日期/時間格式 比如 '%Y-%m-%d %H:%M:%S'  2016-06-14 10:10:00。
level            指定logger的日誌級別。
stream        使用指明的流來初始化StreamHandler。該引數與'filename'不相容,如果兩個都有,'stream'將被忽略。
  1. #!/usr/bin/python
  2. # -*- coding:utf-8 -*-
  3. import logging
  4. logging.basicConfig(level=logging.DEBUG,
  5.                 format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
  6.                 datefmt='%Y%m%d %H:%M:%S',
  7.                 filename='myapp.log',
  8.                 filemode='w')
  9. logging.info('info message')
  10. logging.warn('warn message')
  11. logging.error('error message')
  12. logging.critical('critical message')
二  進階介紹
logging模組提供四個元件logger,handler,filter,formatter
logger:記錄器,為應用程式碼提供日誌介面。logger最長用的操作有兩類:配置和傳送日誌訊息。可以透過logging.getLogger(name 獲取logger物件,如果不指定name則返回root物件,如第一個例子。多次使用相同的name呼叫getLogger方法返回同一個logger物件。
呼叫方法:
  1. logger = logging.getLogger(logger_name) #如果不指定 logger_name ,則預設建立一個root logger,見第一個例子。
  2. logger.setLevel(logging.ERROR)          #設定日誌級別為ERROR,即只有日誌級別大於等於ERROR的日誌才會輸出
  3. logger.addHandler(handler_name)         #為logger例項增加一個處理器
  4. logger.removeHandler(handler_name)      # 為logger例項刪除一個處理器
handler:將日誌內容傳送到合適的目的,比如檔案,終端等。一個logger物件可以透過addHandler方法新增0到多個handler,每個handler又可以定義不同日誌級別,以實現日誌分級過濾顯示。
詳細資訊請移步
呼叫方法
  1. StreamHandler
  2. ch = logging.StreamHandler(stream=None)
  3. FileHandler
  4. fh = logging.FileHandler(filename, mode='a', encoding=None, delay=False)
返回FileHandler類的例項。指明的檔案會被開啟,並用作日誌流。如果沒有指明mode,使用'a'。如果encoding不為None,會用指定的編碼來開啟檔案。如果delay為真,只到第一次呼叫emit()的時候才開啟檔案。預設情況下,檔案會一直增長。
filter:提供一種優雅的方式決定一個日誌記錄是否傳送到handler。
formatter:指定日誌記錄輸出的具體格式。formatter的構造方法需要兩個引數:訊息的格式字串和日期字串,這兩個引數都是可選的。
現在我們測試另外一個例子 test_log.py ,該指令碼定義了一個init_log 函式,透過傳入的引數顯示的配置logging。函式里面建立兩個logging 例項,分別將日誌輸出到檔案和終端。
  1. import logging
  2. import logging.handlers
  3. LOG_LEVELS = {'DEBUG': logging.DEBUG,
  4.               'INFO': logging.INFO,
  5.               'ERROR': logging.ERROR,
  6.               'CRITICAL': logging.CRITICAL }
  7. LOGGING_FORMAT = "%(asctime)s - [%(name)s] - [%(levelname)s] - %(message)s" #日誌的輸出的格式
  8. STANDARD_DATE_FORMAT = '%Y-%m-%d %H:%M:%S' #時間格式 2016-06-14 10:10:00
  9. DEFAULT_LOG_MAX_SIZE = 50 * 1024 * 1024    #當達到50M就進行切分
  10. def init_log(logger_name, level='DEBUG', logfile='/tmp/logtest.log',
  11.                  formatter=LOGGING_FORMAT, max_size=DEFAULT_LOG_MAX_SIZE):
  12.     logger = logging.getLogger(logger_name)         #初始化一個name為logger_name的logging例項
  13.     logger.setLevel(LOG_LEVELS[level])     #設定日誌的級別
  14.     fh = logging.handlers.RotatingFileHandler(logfile, maxBytes=max_size,backupCount=3)
  15.     #定義日誌輸出到檔案的handler ,也可以定義 fh=logging.FileHandler(logfile)
  16.     fh.setLevel(logging.DEBUG)
  17.     # create console handler with a higher log level
  18.     ch = logging.StreamHandler()           #定義日誌輸出到終端的handler
  19.     ch.setLevel(logging.INFO)
  20.     formatter = logging.Formatter(formatter)
  21.     fh.setFormatter(formatter)
  22.     ch.setFormatter(formatter)
  23.     # add the handlers to the logger
  24.     logger.addHandler(fh)
  25.     logger.addHandler(ch)
  26.     return logger

  27. if __name__ == '__main__':
  28.    LOGGER=init_log('youzan','INFO','0614.log')
  29.    LOGGER.info('info message')
  30.    LOGGER.warn('warn message')
  31.    LOGGER.error('error message')
  32.    LOGGER.critical('critical message')
執行該指令碼 
  1. root@rac4:~# >python logconfig.py
  2. 2016-06-14 10:38:15,190 - [youzan] - [INFO] - info message
  3. 2016-06-14 10:38:15,190 - [youzan] - [WARNING] - warn message
  4. 2016-06-14 10:38:15,191 - [youzan] - [ERROR] - error message
  5. 2016-06-14 10:38:15,191 - [youzan] - [CRITICAL] - critical message
  6. 同時在 0614log 檔案裡面也會記錄對應的log
  7. root@rac4:~# >cat 0614.log
  8. 2016-06-14 10:38:15,190 - [youzan] - [INFO] - info message
  9. 2016-06-14 10:38:15,190 - [youzan] - [WARNING] - warn message
  10. 2016-06-14 10:38:15,191 - [youzan] - [ERROR] - error message
  11. 2016-06-14 10:38:15,191 - [youzan] - [CRITICAL] - critical message
三 擴充 
其實這才是本章的重點,在構建一個整套的程式時,怎麼全域性配置logging 模組,並在不同的程式中呼叫呢?例子如下:
root@rac4:~/python# >tree .
.
├── log2.py          — 引用 logconfig中的logging 配置
├── logconfig.py   —配置logging 輸出格式
特別注意,如果是跨檔案訪問定義的logconfig 配置 ,必須在 logconfig.py 所在的目錄建立 。 
log2.py
  1. import sys
  2. import os
  3. sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
  4. import logging
  5. from logconfig import init_log
  6. logger=init_log('logtest','INFO',log='666.log')  ##透過傳參來定義新的 logging 模組配置。
  7. logger.info('this is a test %s'," yangyi@youzan.com")
  8. logger.debug('debug message')
  9. logger.warn('warn message')
  10. logger.error('error message')
  11. logger.critical('critical message')
  1. root@rac4:~# >python log2.py
  2. 2016-06-14 13:26:50,713 - [logtest] - [INFO] - this is a test yangyi@youzan.com
  3. 2016-06-14 13:26:50,713 - [logtest] - [WARNING] - warn message
  4. 2016-06-14 13:26:50,714 - [logtest] - [ERROR] - error message
  5. 2016-06-14 13:26:50,714 - [logtest] - [CRITICAL] - critical message
四 參考文章
1  
2  



來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22664653/viewspace-2120067/,如需轉載,請註明出處,否則將追究法律責任。

相關文章