Python – logging 類別

Loading

測試環境為 CentOS 8 x86_64 (虛擬機)

參考文章 – https://editor.leonh.space/2022/python-log/ 與 https://iter01.com/578914.html

透過 print 函數可以把執行 python 的訊息顯示在文字命令列上, 如果要把資料導向到檔案或是同時 顯示在文字命令列 並儲存到檔案 這時候可以透過 logging 類別來完成.

使用 logging 類別,有以下 6 個物件.

Logger <- Handler <- Formatter
   |        |
   <<<<<<<<<<<<<< Filter 
  1. Logger (紀錄器) – 用來執行日誌紀錄,透過 logging.getLogger(name=None) 來生成 .
  2. Handler (處理器) – 選擇日誌的輸出地方,常用的 Handler ,生成後透過 logger.addHandler(hdlr) 把 Handler 加到 Logger .
    • StreamHandler – 透過 logging.StreamHandler(stream=None) 來生成, 將資料輸出到標準輸出 sys.stdout, sys.stderr 或是 file-like object .
    • FileHandler – 透過 logging.FileHandler(filename, mode=’a’, encoding=None, delay=False, errors=None) 來生成 ,將資料儲存成檔案.
  3. Formatter (格式器) – 顯示訊息的格式, 透過 logging.Formatter(fmt=None, datefmt=None, style=’%’, validate=True, *, defaults=None)來生成, 生成後透過 Handler.setFormatter(fmt) 把 Formatter 加到 Handler .
  4. Filter (過濾器) – 用來控制訊息的輸出內容,看是要加到 logger 或是 Handler ,當你要所有的 Handler 都使用相同的 Filter 時就在 logger 物件透過 logger.addFilter(filter) 來生成 ,想要在個別 Handler 使用時就在 Handler 物件透過 handler.addFilter(filter) 來生成 .
  5. LogRecord – 產生 Logger 時自動生成.
  6. LoggerAdapter – 沒使用過.

使用以下範例來看一下這幾個物件的使用.

  1. 範例 : 生成 Logger 的用法
    [root@localhost ~]# vi logger.py
    import logging
    
    logger = logging.getLogger(__name__)
    
    logger.debug('debug message')
    logger.info('info message')
    logger.warning('warning message')
    logger.error('error message')
    logger.critical('critical message')
    

    執行結果

    [root@localhost ~]# python3 logger.py
    warning message
    error message
    critical message
    

    說明:
    匯入 logging 套件.

    import logging
    

    透過 logging.getLogger 建立屬於自己的 logging instance (這樣可以使用自己設定的組態,可依據需求將執行結果儲存到不同的檔案,並賦予不同的輸出格式),我們也是可以直接使用 logging 但會影響到 root 的 logging 的設定.

    帶入參數使用 __name__ 使用在模組時 Formatter 的 %(name)s 顯示其模組名稱.

    logger = logging.getLogger(__name__)
    

    透過建立好的 logger 來產生 不同 等級的訊息.預設等級大於 WARNING ,以上的訊息才會被記錄起來,等級如下:
    NOTSET < DEBUG < INFO < WARNING < ERROR < CRITICAL

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

    結果

    warning message
    error message
    critical message
    
  2. 範例 : 生成 handler + setLevel 的用法
    [root@localhost ~]# vi handler.py 
    import logging
    
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.DEBUG)
    
    handler = logging.StreamHandler()
    logger.addHandler(handler)
    
    logger.debug('debug message')
    logger.info('info message')
    logger.warning('warning message')
    logger.error('error message')
    logger.critical('critical message')
    

    執行結果

    [root@localhost ~]# python3 handler.py 
    debug message
    info message
    warning message
    error message
    critical message
    

    說明:
    logging 類別預設要等級大於 WARNING ,以上的訊息才會被記錄起來,等級如下:
    NOTSET < DEBUG < INFO < WARNING < ERROR < CRITICAL

    把預設的 WARNING 設定變更為 Debug 以上皆會紀錄.

    logger.setLevel(logging.DEBUG)
    

    除了剛剛建立好的 logger 我們還需要透過 logging.StreamHandler 建立 handler ,該類別主要負責訊息的輸出到 sys.stdout, sys.stderr 或是 file-like object (支援 write() 與 flush() 的 methods ) .

    handler = logging.StreamHandler()
    

    生成後透過 logger.addHandler(hdlr) 把 Handler 加到 Logger .我們可以透過定義多個 handler (後面範例) 來讓訊息同時顯示在 文字命令列 並儲存到檔案裡面.

    logger.addHandler(handler)
    
  3. 範例 : 生成 formatter 來變更改資料輸出格式的用法
    [root@localhost ~]# vi formatter.py
    import logging
    
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.DEBUG)
    
    handler = logging.StreamHandler()
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    handler.setFormatter(formatter)
    logger.addHandler(handler)
    
    logger.debug('debug message')
    logger.info('info message')
    logger.warning('warning message')
    logger.error('error message')
    logger.critical('critical message')
    

    執行結果

    [root@localhost ~]# python3 lformatter.py 
    2022-05-25 23:36:48,078 - __main__ - DEBUG - debug message
    2022-05-25 23:36:48,078 - __main__ - INFO - info message
    2022-05-25 23:36:48,078 - __main__ - WARNING - warning message
    2022-05-25 23:36:48,078 - __main__ - ERROR - error message
    2022-05-25 23:36:48,078 - __main__ - CRITICAL - critical message
    

    說明:
    透過 logging.Formatter(fmt=None, datefmt=None, style=’%’, validate=True, *, defaults=None)來生成,各式格式請參考說明 – https://docs.python.org/3/library/logging.html#logrecord-attributes

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

    生成後透過 Handler.setFormatter(fmt) 把 Formatter 加到 Handler .

    handler.setFormatter(formatter)
    
  4. 範例 : 生成 handler 來變更改資料輸出到檔案的用法
    [root@localhost ~]# vi FileHandler.py 
    import logging
    
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.DEBUG)
    
    handler = logging.FileHandler('filehandler.log')
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    handler.setFormatter(formatter)
    logger.addHandler(handler)
    
    logger.debug('debug message')
    logger.info('info message')
    logger.warning('warning message')
    logger.error('error message')
    logger.critical('critical message')
    

    執行結果

    [root@localhost ~]# python3 FileHandler.py 
    
    [root@localhost ~]# cat filehandler.log 
    2022-05-31 13:24:41,336 - __main__ - DEBUG - debug message
    2022-05-31 13:24:41,336 - __main__ - INFO - info message
    2022-05-31 13:24:41,336 - __main__ - WARNING - warning message
    2022-05-31 13:24:41,336 - __main__ - ERROR - error message
    2022-05-31 13:24:41,336 - __main__ - CRITICAL - critical message
    

    說明:
    透過 logging.FileHandler(filename, mode=’a’, encoding=None, delay=False, errors=None) 來生成 ,將資料儲存成檔案.

    handler = logging.FileHandler('filehandler.log')
    
  5. 範例 : 生成不同 handler 來讓資料同時輸出到文字命令列與檔案的方法
    [root@localhost ~]# vi 2handler.py 
    import logging
    
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.DEBUG)
    
    handler1 = logging.FileHandler('2handler.log')
    handler2 = logging.StreamHandler()
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    
    handler1.setFormatter(formatter)
    handler2.setFormatter(formatter)
    logger.addHandler(handler1)
    logger.addHandler(handler2)
    
    logger.debug('debug message')
    logger.info('info message')
    logger.warning('warning message')
    logger.error('error message')
    logger.critical('critical message')
    

    執行結果

    [root@localhost ~]# python3 2handler.py 
    2022-05-31 13:26:59,835 - __main__ - DEBUG - debug message
    2022-05-31 13:26:59,835 - __main__ - INFO - info message
    2022-05-31 13:26:59,835 - __main__ - WARNING - warning message
    2022-05-31 13:26:59,835 - __main__ - ERROR - error message
    2022-05-31 13:26:59,836 - __main__ - CRITICAL - critical message
    
    [root@localhost ~]# cat 2handler.log 
    2022-05-31 13:26:59,835 - __main__ - DEBUG - debug message
    2022-05-31 13:26:59,835 - __main__ - INFO - info message
    2022-05-31 13:26:59,835 - __main__ - WARNING - warning message
    2022-05-31 13:26:59,835 - __main__ - ERROR - error message
    2022-05-31 13:26:59,836 - __main__ - CRITICAL - critical message
    

    說明:
    生成 2 個,一個 handler 指向 文字命令列 另外一個指向 檔案(使用相同的格式 formatter).

    handler1 = logging.FileHandler('2handler.log')
    handler2 = logging.StreamHandler()
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    
    handler1.setFormatter(formatter)
    handler2.setFormatter(formatter)
    logger.addHandler(handler1)
    logger.addHandler(handler2)
    
沒有解決問題,試試搜尋本站其他內容

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料