一、從乙個使用場景開始
開發乙個日誌系統, 既要把日誌輸出到控制台, 還要寫入日誌檔案
import logging
# 建立乙個logger
logger = logging.getlogger('mylogger')
logger.setlevel(logging.debug)
# 建立乙個handler,用於寫入日誌檔案
fh = logging.filehandler('test.log')
fh.setlevel(logging.debug)
# 再建立乙個handler,用於輸出到控制台
ch = logging.streamhandler()
ch.setlevel(logging.debug)
# 定義handler的輸出格式
formatter = logging.formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setformatter(formatter)
ch.setformatter(formatter)
# 給logger新增handler
logger.addhandler(fh)
logger.addhandler(ch)
# 記錄一條日誌
logger.info('foorbar')
執行後, 在控制台和日誌檔案都有一條日誌:
2011-08-31 19:18:29,816 - mylogger - info - foorbar
二、logging模組的api結合上面的例子,我們說下幾個最常使用的api
logging.
getlogger([
name])
返回乙個logger例項,如果沒有指定name,返回root logger。
只要name相同,返回的logger例項都是同乙個而且只有乙個,即name和logger例項是
一一對應的。
這意味著,無需把logger例項在各個模組中傳遞。只要知道name,就能得到
同乙個logger例項
logger.
setlevel
(lvl
)設定logger的level, level有以下幾個級別:
notset < debug < info < warning < error < critical
如果把looger的級別設定為info, 那麼小於info級別的日誌都不輸出, 大於等於info級
別的日誌都輸出
logger.debug("foobar") # 不輸出
logger.info("foobar") # 輸出
logger.warning("foobar") # 輸出
logger.error("foobar") # 輸出
logger.critical("foobar") # 輸出
logger.
addhandler
(hdlr
)logger可以僱傭handler來幫它處理日誌, handler主要有以下幾種:
streamhandler: 輸出到控制台
filehandler: 輸出到檔案
handler還可以設定自己的level以及輸出格式。
logging.
basicconfig([
**kwargs])
* 這個函式用來配置root logger, 為root logger建立乙個streamhandler,
設定預設的格式。
* 這些函式: logging.debug()、logging.info()、logging.warning()、
logging.error()、logging.critical()
如果呼叫的時候發現root logger沒有任何
handler, 會自動呼叫basicconfig新增乙個handler
* 如果root logger已有handler, 這個函式不做任何事情
使用basicconfig來配置root logger的輸出格式和level:
import logging
logging.basicconfig(format='%(levelname)s:%(message)s', level=logging.debug)
三、關於root logger以及logger的父子關係
前面多次提到root logger, 實際上logger例項之間還有父子關係, root logger就是處於
最頂層的logger, 它是
所有logger的祖先。如下圖:root logger是預設的logger如果不建立logger例項, 直接呼叫logging.debug()、logging.info()logging.warning()、logging.error()、logging.critical()這些函式,
那麼使用的logger就是 root logger, 它可以自動建立,也是單例項的。
如何得到root logger通過logging.getlogger()或者logging.getlogger("")得到root logger例項。
預設的levelroot logger預設的level是logging.warning
如何表示父子關係logger的name的命名方式可以表示logger之間的父子關係. 比如:
parent_logger = logging.getlogger('foo')
child_logger = logging.getlogger('foo.bar')
什麼是effective levellogger有乙個概念,叫effective level。 如果乙個logger沒有顯示地設定level,那麼它就
用父親的level。如果父親也沒有顯示地設定level, 就用父親的父親的level,以此推....
最後到達root logger,一定設定過level。預設為logging.warning
child loggers得到訊息後,既把訊息分發給它的handler處理,也會傳遞給所有祖先logger
處理,來看乙個例子
import logging輸出如下:# 設定root logger
r = logging.getlogger()
ch = logging.streamhandler()
ch.setlevel(logging.debug)
formatter = logging.formatter('%(asctime)s - %(levelname)s - %(message)s')
ch.setformatter(formatter)
r.addhandler(ch)
# 建立乙個logger作為父親
p = logging.getlogger('foo')
p.setlevel(logging.debug)
ch = logging.streamhandler()
ch.setlevel(logging.debug)
formatter = logging.formatter('%(asctime)s - %(message)s')
ch.setformatter(formatter)
p.addhandler(ch)
# 建立乙個孩子logger
c = logging.getlogger('foo.bar')
c.debug('foo')
2011-08-31 21:04:29,893 - foo
2011-08-31 21:04:29,893 - debug - foo
可見, 孩子logger沒有任何handler,所以對訊息不做處理。但是它把訊息**給了它的父
親以及root logger。
最後輸出兩條日誌。
詳解Python中的日誌模組logging
許多應用程式中都會有日誌模組,用於記錄系統在執行過程中的一些關鍵資訊,以便於對系統的執行狀況進行跟蹤。在.net平台中,有非常著名的第三方開源日誌元件log4net,c 中,有人們熟悉的log4cpp,而在python中,我們不需要第三方的日誌元件,因為它已經為我們提供了簡單易用 且功能強大的日誌模...
記憶碎片之scrapy中使用logging模快
settings.py log level warning 設定日誌顯示的等級 log file a.log 設定日誌儲存的位置,設定後介面不會顯示日誌內容 spider.py import logging import logging logging.basicconfig函式各引數 filena...
python元類的使用 python使用元類
原文 type 動態語言和靜態語言最大的不同,就是函式和類的定義,不是編譯時定義的,而是執行時動態建立的。比方說我們要定義乙個hello的class,就寫乙個hello.py模組 當python直譯器載入hello模組時,就會依次執行該模組的所有語句,執行結果就是動態建立出乙個hello的class...