Python日誌模組簡介
使用Python寫程式,有時要用上日誌系統。特別是Python這樣的動態語言,很多錯誤都只能在啟動並執行時候才能發現,一個好的日誌系統對於Python程式相當重要。
最簡單的解決方案當然是直接使用print輸出運行資訊。但是這樣太簡單了,沒有分級功能,如果在發布的時候想去掉調試用的運行資訊還得找出所有的print語句進行修改。再者,print只能輸出到控制台,想要輸出到檔案或者通過電子郵件發送到其他地方,一個 print語句就沒辦法解決了。
通過使用Python的日誌系統,就可以解決以上問題。 首先看一下這個樣本:
import logging
logger=logging.getLogger(’應用程式名稱’)
logger.setLevel(logging.DEBUG)
console = logging.StreamHandler()
console.setLevel(logging.INFO)
logger.addHandler(console)
logger.debug(’調試資訊’)
logger.info(’有用的資訊’)
logger.warning(’警告資訊’)
logger.error(’錯誤資訊’)
logger.critical(’嚴重錯誤資訊’)
上面的代碼想控制台輸出了五種錯誤資訊。分為五個從低到高的層級,從DEBUG到CRITICAL。此外,我們還指定了程式輸出的層級,只有INFO層級以上的資訊才會被輸出。
Python的日誌核心組件:
1. “Logger”。每個程式在輸出資訊之前都要獲得一個Logger。Logger通常對應了程式的模組名,
比如聊天工具的圖形介面模組可以這樣獲得它的Logger:
logger=logging.getLogger(”chat.gui”)
而核心模組可以這樣:
logger=logging.getLogger(”chat.kernel”)
我們接下來可以看到使用這種命名方法的用途。 還有直接使用:
logger= logging.getLogger()
#或
logger = logging.basicConfig(**kwargs)
其中預設的日誌name為root,直接使用logging模組的info、debug等函數,會把日誌都記錄在root層。
2. "formatter":
日誌格式化
日誌的輸出格式是通過logging.Formatter來設定的,其初始化的參數如下: 例如:
logger=logging.getLogger(”chat.gui”)
console = logging.StreamHandler()
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
console .setFormatter(formatter)
logger.addHandler(console)
#或
logging.basicConfig(filename = os.path.join(os.getcwd(), 'log.txt' ), /
level = logging.WARN, filemode = 'w' , format = '%(asctime)s -/
%(levelname)s: %(message)s' )
logging.debug('debug' ) #被忽略
logging.info('info' ) #被忽略
logging.warning('warn' )
logging.error('error' )
#----- 結果
#2009-07-13 21:42:15,592 - WARNING: warn
#2009-07-13 21:42:15,640 - ERROR: error
3. “Handler”。
用於處理常式的輸出。 Python的日誌系統有多種Handler可以使用。有些Handler可以把資訊輸出到控制台,有些Logger可以把資訊輸出到檔案,還有些 Handler可以把資訊發送到網路上。如果覺得不夠用,還可以編寫自己的Handler。
所有的Handler可以支援三個操作:
A.設定輸出格式。比如設定輸出的資訊中包含時間和層級資訊:
logger=logging.getLogger(”chat.gui”)
console = logging.StreamHandler()
console.setLevel(logging.INFO)
formatter = logging.Formatter(’%(asctime)s - %(levelname)s - %(message)s’)
console.setFormatter(formatter)
logger.addHandler(console)
B. 設定輸出層級
在上面我們已經示範了如何設定輸出層級了。除了Python內建的五種層級,我們還可以自訂輸出層級。
日誌對象對於不同的層級資訊提供不同的函數進行輸出,如:info(), error(), debug()等。當寫入日誌時,小於指定層級的資訊將被忽略。因此為了輸出想要的記錄層級一定要設定好此參數。這裡我設為NOTSET(值為0),也就是想輸出所有資訊。系統預設的記錄層級排序為,CRITICAL,ERROR,WARNING,INFO,DEBUG,NOTSET。比如說我們要輸出的資訊為CRITICAL,但是我們的記錄層級為DEBUG,那麼這個資訊將被忽略掉。
C.設定過濾器
前文調用logging.getLogger()時參數的格式類似於“A.B.C”。採取這樣的格式其實就是為了可以配置過濾器。看一下這段代碼:
logger=logging.getLogger(”chat.gui.statistic”)
console = logging.StreamHandler()
console.setLevel(logging.INFO)
formatter = logging.Formatter(’%(asctime)s %(levelname)s %(message)s’)
console.setFormatter(formatter)
filter=logging.Filter(”chat.gui”)
console.addFilter(filter)
logger.addHandler(console
和前面不同的是我們在Handler上添加了一個過濾器。現在我們輸出日誌資訊的時候就會經過過濾器的處理。名為“A.B”的過濾器只讓名字帶有 “A.B”首碼的Logger輸出資訊。可以添加多個過濾器,只要有一個過濾器拒絕,日誌資訊就不會被輸出。另外,在Logger中也可以添加過濾器。 每個Logger可以附加多個Handler。
接下來我們就來介紹一些常用的Handler:
- logging.StreamHandler
使用這個Handler可以向類似與sys.stdout或者sys.stderr的任何檔案對象(file object)輸出資訊。它的建構函式是: StreamHandler([strm]) 其中strm參數是一個檔案對象。預設是sys.stderr
- logging.FileHandler
和StreamHandler類似,用於向一個檔案輸出日誌資訊。不過FileHandler會幫你開啟這個檔案。它的建構函式是: FileHandler(filename[,mode]) filename是檔案名稱,必須指定一個檔案名稱。 mode是檔案的開啟檔案。參見Python內建函數open()的用法。預設是’a',即添加到檔案末尾。
- logging.handlers.RotatingFileHandler
這個Handler類似於上面的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並不會被更名,而是被刪除。
- logging.handlers.TimedRotatingFileHandler
這個Handler和RotatingFileHandler類似,不過,它沒有通過判斷檔案大小來決定何時重新建立記錄檔,而是間隔一定時間就 自動建立新的記錄檔。重新命名的過程與RotatingFileHandler類似,不過新的檔案不是附加數字,而是目前時間。它的建構函式是: TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]]) 其中filename參數和backupCount參數和RotatingFileHandler具有相同的意義。 interval是時間間隔。 when參數是一個字串。表示時間間隔的單位,不區分大小寫。它有以下取值: S 秒 M 分 H 小時 D 天 W 每星期(interval==0時代表星期一) midnight 每天淩晨
- logging.handlers.SocketHandler
- logging.handlers.DatagramHandler
以上兩個Handler類似,都是將日誌資訊發送到網路。不同的是前者使用TCP協議,後者使用UDP協議。它們的建構函式是: Handler(host, port) 其中host是主機名稱,port是連接埠名
- logging.handlers.SysLogHandler
- logging.handlers.NTEventLogHandler
- logging.handlers.SMTPHandler
- logging.handlers.MemoryHandler
- logging.handlers.HTTPHandler
學習資料:http://onlamp.com/pub/a/python/2005/06/02/logging.html