(轉)一篇寫的簡明易懂的logging模塊

轉:http://kenby.iteye.com/blog/1162698html

 

1、從一個使用場景開始python

 

開發一個日誌系統, 既要把日誌輸出到控制檯, 還要寫入日誌文件app

 

Python代碼   收藏代碼
  1. import logging  
  2.   
  3. # 建立一個logger  
  4. logger = logging.getLogger('mylogger')  
  5. logger.setLevel(logging.DEBUG)  
  6.   
  7. # 建立一個handler,用於寫入日誌文件  
  8. fh = logging.FileHandler('test.log')  
  9. fh.setLevel(logging.DEBUG)  
  10.   
  11. # 再建立一個handler,用於輸出到控制檯  
  12. ch = logging.StreamHandler()  
  13. ch.setLevel(logging.DEBUG)  
  14.   
  15. # 定義handler的輸出格式  
  16. formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')  
  17. fh.setFormatter(formatter)  
  18. ch.setFormatter(formatter)  
  19.   
  20. # 給logger添加handler  
  21. logger.addHandler(fh)  
  22. logger.addHandler(ch)  
  23.   
  24. # 記錄一條日誌  
  25. logger.info('foorbar')  
 

 

運行後, 在控制檯和日誌文件都有一條日誌:函數

 

Java代碼   收藏代碼
  1. 2011-08-31 19:18:29,816 - mylogger - INFO - foorbar  

 

 

2、logging模塊的APIspa

 

結合上面的例子,咱們說下幾個最常使用的APIdebug

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級別的日誌都輸出
Python代碼   收藏代碼
  1. logger.debug("foobar")    # 不輸出   
  2. logger.info("foobar")        # 輸出  
  3. logger.warning("foobar") # 輸出  
  4. logger.error("foobar")      # 輸出  
  5. 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:
Python代碼   收藏代碼
  1. import logging  
  2. logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG)  
  3. logging.debug('This message should appear on the console')  
 
3、關於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.WARNINGchild loggers獲得消息後,既把消息分發給它的handler處理,也會傳遞給全部祖先logger處理,
來看一個例子
Python代碼   收藏代碼
  1. import logging  
  2.   
  3. # 設置root logger  
  4. r = logging.getLogger()  
  5. ch = logging.StreamHandler()  
  6. ch.setLevel(logging.DEBUG)  
  7. formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')  
  8. ch.setFormatter(formatter)  
  9. r.addHandler(ch)  
  10.   
  11. # 建立一個logger做爲父親  
  12. p = logging.getLogger('foo')  
  13. p.setLevel(logging.DEBUG)  
  14. ch = logging.StreamHandler()  
  15. ch.setLevel(logging.DEBUG)  
  16. formatter = logging.Formatter('%(asctime)s - %(message)s')  
  17. ch.setFormatter(formatter)  
  18. p.addHandler(ch)  
  19.   
  20. # 建立一個孩子logger  
  21. c = logging.getLogger('foo.bar')  
  22. c.debug('foo')  
 輸出以下:
Python代碼   收藏代碼
  1. 2011-08-31 21:04:29,893 - foo  
  2. 2011-08-31 21:04:29,893 - DEBUG - foo  

可見, 孩子logger沒有任何handler,因此對消息不作處理。可是它把消息轉發給了它的父親以及root logger。最後輸出兩條日誌。
  • 大小: 2 KB
  • 大小: 10.1 KB
相關文章
相關標籤/搜索