2011-09-22 43 views
6

我真的錯過了關於python日誌記錄模塊的基本知識。幫我理解python的日誌記錄模塊及其處理程序

在下面的代碼中,我創建了一個記錄器對象(log)並添加了兩個處理程序。一個與 'INFO'級別和一個'警告'級別。他們都應該打印到標準輸出。我希望調用log.info(msg) 將在我的標準輸出中產生msg的一個副本,並且調用log.warn(msg)可以產生 兩個副本msg打印到我的標準輸出。這裏是代碼:

import logging 
import sys 


logging.basicConfig() 
log = logging.getLogger('myLogger') 
log.handlers = [] 
h1 = logging.StreamHandler(sys.stdout) 
h1.level = logging.INFO 
h1.formatter = logging.Formatter('H1 H1 %(message)s ') 
h2 = logging.StreamHandler(sys.stdout) 
h2.level = logging.WARNING 
h2.formatter = logging.Formatter('H2 H2 %(message)s') 
log.addHandler(h1) 
log.addHandler(h2) 

print 'log.level == %s'%logging.getLevelName(log.level) 
print 'log.info' 
log.info('this is some info') 
print 'done' 
print 'log.warn' 
log.warn('this is a warning') 
print 'done' 

輸出對我來說真的很奇怪。呼叫.info不會導致視覺效果。 但是,調用warn會導致將兩個msg打印到stdout(這是OK),但也會將一個副本打印到stderr(爲什麼?)。這是上述代碼的輸出。請注意此輸出中最後一行的格式。這一行打印到stderr。

log.level == NOTSET 
log.info 
done 
log.warn 
H1 H1 this is a warning 
H2 H2 this is a warning 
done 
WARNING:myLogger:this is a warning 

所以我的問題是:

  1. 爲什麼,我呼籲info沒有輸出結果儘管h1的級別設置爲INFO的事實?
  2. 爲什麼我打電話給warn會導致額外的輸出到stderr?
+0

我不能肯定,但你可能會運行到麻煩,因爲Python的'logging'有警告和信息一個內置的水平。 – brc

+0

@brc這會回答我的第一個問題,但不是第二個問題 –

回答

7

有兩件事情你需要知道:

  1. 根記錄器的初始化級別爲WARNING

    如果達到記錄器的任何日誌消息的級別低於記錄器的級別,則會被丟棄。如果沒有設置記錄器的級別,它將從其父記錄器獲取「有效級別」。因此,如果根記錄器的級別爲WARNING,則所有記錄器的默認有效級別爲WARNING。如果您沒有配置它,則所有低於該級別的日誌消息將被丟棄。

  2. 當您撥打basicConfig()時,系統會在根記錄器上自動設置打印到標準錯誤流的StreamHandler

    當你的程序打印出它的日誌消息,實際上有處理程序:您已添加了兩下,它們有自己的水平,和一個從系統將打印出不被拒絕的任何消息它的記錄器。這就是爲什麼你得到該行

    WARNING:myLogger:this is a warning 
    

    它來自系統記錄器。它不會爲INFO級別的消息執行此操作,因爲如前所述,默認情況下會將根日誌記錄器配置爲拒絕這些消息。

    如果您不想要這個輸出,請不要撥打basicConfig()

延伸閱讀:http://docs.python.org/howto/logging.html

3

實際上有五個級別的日誌記錄:debug,info,warning,error和critical。我發現當你設置你的記錄器時,你沒有明確設定你的級別 - 我相信如果沒有設置級別,記錄器可能會默認爲警告。至於爲什麼它會多次打印出警告,我相信這是由於您爲信息&警告創建了兩個處理程序。會發生什麼情況是記錄器級聯嚴重性從警告 - >信息 - >調試,調用每個處理程序。由於您的級別設置爲警告,所以信息處理程序將被忽略。另外,我相信警告消息通常寫入sys.stderr。

嘗試以下操作:

logging.basicConfig(level=logging.INFO) 

參見:

+0

哈,像我一樣抓住了我的錯誤 - 不知何故,這使我成爲雙後? –

+0

更具體地說,在他的示例中,@bgbg設置處理程序的級別,但從不設置記錄程序的級別。因此記錄器的級別默認爲'logging.WARNING'。添加'log.level = logging.INFO'會解決這個問題。我同意@David Z認爲最好完全除去'basicConfig()'調用,而不要依賴根記錄器。 –

相關問題