2011-07-18 86 views
36

我正在使用Python日誌記錄,出於某種原因,我的所有消息都出現了兩次。日誌消息與Python日誌出現兩次

我有一個模塊配置日誌:

# BUG: It's outputting logging messages twice - not sure why - it's not the propagate setting. 
def configure_logging(self, logging_file): 
    self.logger = logging.getLogger("my_logger") 
    self.logger.setLevel(logging.DEBUG) 
    self.logger.propagate = 0 
    # Format for our loglines 
    formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") 
    # Setup console logging 
    ch = logging.StreamHandler() 
    ch.setLevel(logging.DEBUG) 
    ch.setFormatter(formatter) 
    self.logger.addHandler(ch) 
    # Setup file logging as well 
    fh = logging.FileHandler(LOG_FILENAME) 
    fh.setLevel(logging.DEBUG) 
    fh.setFormatter(formatter) 
    self.logger.addHandler(fh) 

後來,我把這種方法來配置日誌記錄:

if __name__ == '__main__': 
    tom = Boy() 
    tom.configure_logging(LOG_FILENAME) 
    tom.buy_ham() 

內,然後說了,buy_ham模塊,我會打電話:

self.logger.info('Successfully able to write to %s' % path) 

由於某種原因,所有消息都出現兩次。我評論了一個流處理程序,仍然是同樣的事情。一個奇怪的位,不知道爲什麼會發生這種情況......大聲笑。假設我錯過了一些明顯的事情。

乾杯, 維克多

+0

你確定'configure_logging()'沒有被調用兩次(例如從構造函數中)?是否只創建Boy()的一個實例? –

回答

60

要調用configure_logging兩次(也許在Boy__init__法):getLogger將返回相同的對象,但如果類似的處理程序已經被添加到記錄器addHandler不檢查。

嘗試對該方法進行跟蹤調用並刪除其中的一個。或設置標誌logging_initializedBoy__init__方法初始化爲False,改變configure_logging做什麼,如果logging_initializedTrue,並將其設置爲True你初始化記錄器之後。

如果你的程序中創建多個Boy情況下,你必須改變你做事與全球configure_logging功能附加的處理方式,以及Boy.configure_logging方法只初始化self.logger屬性。

解決此的另一種方式是通過檢查你的記錄器的處理程序屬性:

logger = logging.getLogger('my_logger') 
if not logger.handlers: 
    # create the handlers and call logger.addHandler(logging_handler) 
+1

是的,你是對的 - 傻我。我在__init__中以及在其他地方明確地調用了它。大聲笑。謝謝=)。 – victorhooi

+0

謝謝。你的解決方案今天救了我。 – Tammy

+1

就我而言,他們出現了6次。我懷疑是因爲我已經在6個OOP類 – answerSeeker

5

處理程序會在每次從外面打電話時添加。嘗試Removeing處理程序完成自己的工作後:

self.logger.removeHandler(ch) 
+0

我在python 2.7中使用了'logger.handlers.pop()', – radtek

2

我是一個Python新手,但是這似乎爲我工作(Python 2.7版)

while logger.handlers: 
    logger.handlers.pop() 
1

如果您看到了這個問題,你「再沒有添加處理兩次,然後看到abarnert的答案here

docs

注意:如果您將處理程序附加到記錄器及其一個或多個 祖先,它可能會多次發出相同的記錄。一般來說,您不需要將處理程序附加到多個記錄程序 - 如果您只需將其附加到 記錄程序層次結構中最高的相應記錄程序,那麼它將查看所​​有記錄程序記錄的所有事件記錄程序,只要它們的傳播設置保持爲True。A 常見的情況是將處理程序僅附加到根記錄器,並讓讓傳播處理其餘部分。

所以,如果你想在「測試」自定義處理程序,而你不想它的消息也給根處理,答案很簡單:關掉它的繁殖標誌:

記錄儀.propagate = False