開發(fā)Python, 一直以來都是使用自己編寫的logging模塊. 比較土...... 今天發(fā)現(xiàn)python的標準模塊的這個功能做的挺好, 記錄一下, 以后使用模塊來進行l(wèi)ogging. 對于這個模塊的介紹網(wǎng)上也很多, 我也不用自己寫了, 比較好的如下, http://crazier9527./blog/290018 Python的標準logging模塊 http://blog./2010/06/03/python-logging-module/ Python的logging模塊 http://docs./library/logging.html 官方文檔 下面就對于在項目中比較需要用到的部分摘錄一些, 簡單的例子
上面這段代碼基本包含logging模塊的基本feature GetLogger
GetLogger() returns a reference to a logger instance with the specified name if it is provided, or root if not. The names are period-separated hierarchical structures. Multiple calls to getLogger() with the same name will return a reference to the same logger
object. Formatter Formatter對象定義了最終log信息的順序,結構和內容, 后面會詳細解釋. Handler 這兒用到了StreamHandler和FileHandler, 用于向不同的輸出端打log. SetLevel Logging有如下級別: DEBUG,INFO,WARNING,ERROR,CRITICAL 默認級別是WARNING, logging模塊只會輸出指定level以上的log 這樣的好處, 就是在項目開發(fā)時debug用的log, 在產(chǎn)品release階段不用一一注釋, 只需要調整logger的級別就可以了, 很方便的.
Formatter Formatter對象定義了最終log信息的順序,結構和內容.于基本的logging.Handler類不同,應用可以直接實例化formatter類,當然,如果需要你也可以子例化formatter以便定制它的一些行為.構造函數(shù)接受兩個可選參數(shù):一個信息格式字符串和一個日期格式字符串.如果沒有信息格式字符串,直接輸出log信息.如果沒有日期格式字符串,默認的格式是:%Y-%m-%d %H:%M:%S 上面的代碼給出了Formatter的例子, 下面表格給出所有可以使用的format,
Handler Logging包含很多handler, 可能用到的有下面幾種
最常用的也就是StreamHandler和FileHandler
Configuration
第一種配置方法前面的code里面已經(jīng)有了 第二種配置方法, 我覺得在項目里面是比較實用的, 通過編寫配置文件, 在code里面只需要用fileConfig配置一下logging, 顯得比較簡潔. 這個可以參照http://crazier9527./blog/290026 或 官方文檔.
Multiple handlers and formatters Loggers是一個簡單的Python對象.addHandler()方法沒有最多或者最少配額,當你的應用需要在把所有的log信息打到一個txt文件中去,同時又需要把errors級別一上的錯誤信息打到console時,你就會體會到這個特性的好處.只要簡單的配置一下合適的handlers就可以實現(xiàn)這個功能.應用對logging的調用用不著修改.以下是對前一個基于module的配置例子的改進:
多module使用Logging(只要在同一個Python interpreter process) 上面我曾提到過,所有的對logging.getLogger(‘someLogger’)的調用都會返回同一個對象.這個規(guī)則不僅僅在同一個module有效,而且對在同一個Python的解釋器進程里面的多個module也有效.而且,應用代碼可以在一個module里面定義一個父logger,而在另一個module里面繼承這個logger,所有對這個子logger的調用都會轉到父logger里面去,如下所示: 下面這個是主模塊的代碼,
這個是子模塊的代碼,
可以看到, 我們在主模塊里面定義了一個logger 'spam_application', 并對他進行了配置. 那么在這個解釋器進程里面的任何地方去通過getLogger('spam_application')得到的對象都是一樣的, 不需要從新定義配置, 可以直接使用. 更方便的是, 你定義任意該logger的子logger, 都可以共享父logger的定義和配置 所謂的父子logger只是簡單的通過命名來識別, 任意以'spam_application.'開頭的logger都是他的子logger, 例如'spam_application.auxiliary' 這個在實際的開發(fā)中, 還是很方便的, 對于一個application, 首先通過logging配置文件編寫好這個application所對應的log策略, 可以只生成一個根logger, 比如叫'Project' 然后在Main函數(shù)里面, 通過fileConfig加載logging的配置 接著在appliction的任意地方, 不同的模塊中, 可以使用Project的子logger, 如Project.UI, Project.Core, 來進行l(wèi)og, 并且不需要反復的定義和配置各個logger.
如果使用Python寫一個比較大型的程序,你一定會用上日志系統(tǒng)。特別是Python這樣的動態(tài)語言,很多錯誤都只能在運行的時候才能發(fā)現(xiàn),一個 好的日志系統(tǒng)對于Python程序相當重要。最簡單的解決方案當然是直接使用print輸出運行信息。但是這樣太簡單了,沒有分級功能,如果在發(fā)布的時候 想去掉調試用的運行信息還得找出所有的print語句進行修改。再者,print只能輸出到控制臺,想要輸出到文件或者通過電子郵件發(fā)送到其他地方,一個 print語句就沒辦法解決了。 通過使用Python的日志系統(tǒng),就可以解決以上問題。 首先看一下這個示例: import logging LOG=logging.getLogger(’應用程序名’) console = logging.StreamHandler() console.setLevel(logging.INFO) LOG.addHandler(console) LOG.debug(’調試信息’) LOG.info(’有用的信息’) LOG.warning(’警告信息’) LOG.error(’錯誤信息’) LOG.critical(’嚴重錯誤信息’) 上面的代碼想控制臺輸出了五種錯誤信息。分為五個從低到高的級別,從DEBUG到CRITICAL。此外,我們還指定了程序輸出的級別,只有INFO級別以上的信息才會被輸出。
這就是日志系統(tǒng)最常用的使用方法。這段代碼中有兩個概念可以幫助我們更進一步使用Python的日志系統(tǒng): 1. “Logger”。每個程序在輸出信息之前都要獲得一個Logger。Logger通常對應了程序的模塊名,比如聊天工具的圖形界面模塊可以這樣獲得它的Logger: LOG=logging.getLogger(”chat.gui”) 而核心模塊可以這樣: LOG=logging.getLogger(”chat.kernel”) 我們接下來可以看到使用這種命名方法的用途。 2. “Handler”。用于處理程序的輸出。 Python的日志系統(tǒng)有多種Handler可以使用。有些Handler可以把信息輸出到控制臺,有些Logger可以把信息輸出到文件,還有些 Handler可以把信息發(fā)送到網(wǎng)絡上。如果覺得不夠用,還可以編寫自己的Handler。 所有的Handler可以支持三個操作: 1. 設置輸出格式。比如設置輸出的信息中包含時間和級別信息: LOG=logging.getLogger(”chat.gui”) console = logging.StreamHandler() console.setLevel(logging.INFO) formatter = logging.Formatter(’%(asctime)s %(levelname)s %(message)s’) console.setFormatter(formatter) LOG.addHandler(console) 熟悉Python的朋友應該會發(fā)現(xiàn),logging.Formatter的參數(shù)實際上只是Python常用的“%”字符串格式化。它使用“%(name)s”表示占位符。下面是一個完整的表格,展示了日志系統(tǒng)可以輸出的各種信息: %(name)s Logger的名字 %(levelno)s 數(shù)字形式的日志級別 %(levelname)s 文本形式的日志級別 %(pathname)s 調用日志輸出函數(shù)的模塊的完整路徑名,可能沒有 %(filename)s 調用日志輸出函數(shù)的模塊的文件名 %(module)s 調用日志輸出函數(shù)的模塊名 %(funcName)s 調用日志輸出函數(shù)的函數(shù)名 %(lineno)d 調用日志輸出函數(shù)的語句所在的代碼行 %(created)f 當前時間,用UNIX標準的表示時間的浮點數(shù)表示 %(relativeCreated)d 輸出日志信息時的,自Logger創(chuàng)建以來的毫秒數(shù) %(asctime)s 字符串形式的當前時間。默認格式是“2003-07-08 16:49:45,896”。逗號后面的是毫秒 %(thread)d 線程ID。可能沒有 %(threadName)s 線程名。可能沒有 %(process)d 進程ID??赡軟]有 %(message)s 用戶輸出的消息 2. 設置輸出級別 在上面我們已經(jīng)演示了如何設置輸出級別了。除了Python內置的五種級別,我們還可以自定義輸出級別。 TODO 子定義輸出級別 3. 設置過濾器 細心的朋友一定會發(fā)現(xiàn)前文調用logging.getLogger()時參數(shù)的格式類似于“A.B.C”。采取這樣的格式其實就是為了可以配置過濾器??匆幌逻@段代碼: LOG=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) LOG.addHandler(console) 和前面不同的是我們在Handler上添加了一個過濾器。現(xiàn)在我們輸出日志信息的時候就會經(jīng)過過濾器的處理。名為“A.B”的過濾器只讓名字帶有 “A.B”前綴的Logger輸出信息。可以添加多個過濾器,只要有一個過濾器拒絕,日志信息就不會被輸出。另外,在Logger中也可以添加過濾器。 每個Logger可以附加多個Handler。接下來我們就來介紹一些常用的Handler: 1) logging.StreamHandler 使用這個Handler可以向類似與sys.stdout或者sys.stderr的任何文件對象(file object)輸出信息。它的構造函數(shù)是: StreamHandler([strm]) 其中strm參數(shù)是一個文件對象。默認是sys.stderr 2) 2.logging.FileHandler 和StreamHandler類似,用于向一個文件輸出日志信息。不過FileHandler會幫你打開這個文件。它的構造函數(shù)是: FileHandler(filename[,mode]) filename是文件名,必須指定一個文件名 mode是文件的打開方式。參見Python內置函數(shù)open()的用法。默認是’a',即添加到文件末尾。 3) 3.logging.handlers.RotatingFileHandler 這個Handler類似于上面的FileHandler,但是它可以管理文件大小。當文件達到一定大小之后,它會自動將當前日志文件改名,然后創(chuàng)建 一個新的同名日志文件繼續(xù)輸出。比如日志文件是chat.log。當chat.log達到指定的大小之后,RotatingFileHandler自動把 文件改名為chat.log.1。不過,如果chat.log.1已經(jīng)存在,會先把chat.log.1重命名為chat.log.2。。。最后重新創(chuàng)建 chat.log,繼續(xù)輸出日志信息。它的構造函數(shù)是: RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]]) 其中filename和mode兩個參數(shù)和FileHandler一樣。 maxBytes用于指定日志文件的最大文件大小。如果maxBytes為0,意味著日志文件可以無限大,這時上面描述的重命名過程就不會發(fā)生。 backupCount用于指定保留的備份文件的個數(shù)。比如,如果指定為2,當上面描述的重命名過程發(fā)生時,原有的chat.log.2并不會被更名,而是被刪除。 4) 4.logging.handlers.TimedRotatingFileHandler 這個Handler和RotatingFileHandler類似,不過,它沒有通過判斷文件大小來決定何時重新創(chuàng)建日志文件,而是間隔一定時間就 自動創(chuàng)建新的日志文件。重命名的過程與RotatingFileHandler類似,不過新的文件不是附加數(shù)字,而是當前時間。它的構造函數(shù)是: TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]]) 其中filename參數(shù)和backupCount參數(shù)和RotatingFileHandler具有相同的意義。 interval是時間間隔。 when參數(shù)是一個字符串。表示時間間隔的單位,不區(qū)分大小寫。它有以下取值: S 秒M 分H 小時D 天W 每星期(interval==0時代表星期一)midnight 每天凌晨 5) 5.logging.handlers.SocketHandler 6) 6.logging.handlers.DatagramHandler 以上兩個Handler類似,都是將日志信息發(fā)送到網(wǎng)絡。不同的是前者使用TCP協(xié)議,后者使用UDP協(xié)議。它們的構造函數(shù)是: Handler(host, port) 其中host是主機名,port是端口名 7) 7.logging.handlers.SysLogHandler 8) 8.logging.handlers.NTEventLogHandler 9) 9.logging.handlers.SMTPHandler 10) 10.logging.handlers.MemoryHandler 11) 11.logging.handlers.HTTPHandler 這些我自己沒用過,期待大家補充?;蛘邊⒖糚ython的使用手冊 |
|