2018年1月3日 星期三

Python 的日誌

Python 內建就有個 logging 的套件 [1],可以使用設定檔來控制 log 的輸出。
不過實務上有一點小地方需要注意。

disable_existing_loggers

這個參數的意思是,當設定被載入的時候,已經既存的 logger 是否要被關閉。
因為預設是 True,也就是既存的 logger 會被關閉,因此會形成如果程式做過兩次以上的設定載入
有可能會發生有些 logger 寫的 log 在第二次載入後,突然就全部消失了的狀況。

而解法是要嘛把這個屬性設成 False,要嘛就要確保 logger 初始化必須在載入設定之後才發生。
後者就是為什麼 [2] 有一個段落標題這樣寫:

Do not get logger at the module level unless disable_existing_loggers is False

使用 YAML 設定檔

官方文件其實建議新的程式應該要用 dictConfig() 來載入設定檔,因為 dictConfig() 的結構能夠提供更靈活的設定方法。
而 dictConfig() 吃的參數是 dictionary,因此如果依照官網範例,使用 YAML 格式來寫設定檔時
需要引用 yaml 套件來讀取、解析 YAML 檔案,然後輸出成 dictionary 的格式,才能正確被 dictConfig() 載入。

假設 YAML 的設定檔內容如下:

version: 1
disable_existing_loggers: False
formatters:
  simple:
    format: '%(asctime)s | %(name)s | %(levelname)s | %(message)s'
handlers:
  console:
    class: logging.StreamHandler
    level: DEBUG
    formatter: simple
    stream: ext://sys.stdout
loggers:
  simpleExample:
    level: DEBUG
    handlers: [console]
    propagate: no
root:
  level: DEBUG
  handlers: [console]

載入設定時,需要使用類似這樣的程式碼:

import yaml

with open('logging.yaml', 'r') as fd:
    config = yaml.safe_load(fd.read())
    logging.config.dictConfig(config)
參考資料
  1. 16.6. logging — Logging facility for Python
  2. Good logging practice in Python

沒有留言: