2016-06-28 41 views
0

我的目標是將日誌消息從某個函數重定向到文件中。該功能在另一個模塊中定義。我將StreamHandler添加到主記錄器,但child_call函數未按預期保存到tmp.log從子模塊記錄忽略添加的根記錄器流處理程序

# main.py 

import logging 
import os 
import sys 
from child_logger import child_call 

logging.basicConfig(format='%(name)s:%(filename)s:%(lineno)d:%(message)s', 
     level=logging.INFO, stream=sys.stdout) 

logger = logging.getLogger(__name__) 
logger.info('here it is') 

with open('tmp.log', 'w') as f: 
    logger_stream_handler = logging.StreamHandler(stream=f) 
    logger_stream_handler.setLevel(logging.INFO) 

    logger.addHandler(logger_stream_handler) 
    logger.info('I am outer') 
    child_call() 
    logger.removeHandler(logger_stream_handler) 


# child_logger.py 

import logging 
logger = logging.getLogger(__name__) 

def child_call(): 
    logger.info('I am inner') 

這裏是輸出:

%python logger_test.py             
__main__:logger_test.py:18:here it is                                     
__main__:logger_test.py:25:I am outer                                   
child_logger:child_logger.py:9:I am inner 

%cat tmp.log 
I am outer 

我期待看到 '我內' 的tmp.log。就我所瞭解的日誌記錄模塊而言,創建了一個Logger對象的層次結構,默認情況下,來自子節點的消息應該傳播到根Logger,並且根應該處理所有消息。我錯過了什麼?

回答

1

問題是您的記錄器未正確鏈接。他們需要具有相同的根名稱。例如:

# main.py 
logger = logging.getLogger("parent") 

# child_logger.py 
logger = logging.getLogger("parent.child") 

的兩個日誌檢索只要求有一個__name__記錄儀,它被設置爲模塊的名稱,除了頂層,它得到「__main__」。您正在使用的這相當於結束了:

# main.py 
logger = logging.getLogger("__main__") 

# child_logger.py 
logger = logging.getLogger("child_logger") 

您需要執行一個共同的父記錄名稱方案創建正確的記錄器繼承層次。

+0

謝謝!我認爲日誌記錄會考慮模塊層次結構並在內部調整記錄器名稱以構建相應的層次結構。 – sbond

+0

你有一個想法如何強制* child_logger *使用我想要的處理程序?我無法更改第三方模塊child_logger.py,同時我也不想在getLogger調用中顯式使用模塊名稱。也許有一種方法來獲得一個包含所有可用Logger的迭代器,然後爲它們中的每一個分配一個處理程序? – sbond

+0

@SergiusBond不幸的是我沒有。仔細查看記錄模塊文檔,瞭解可能對您有幫助的功能。如果您沒有找到任何內容,請考慮打開一個新問題(搜索重複內容後)。 – skrrgwasme