2010-05-02 79 views
5

我想以這種方式配置我的Python記錄器,以便記錄器的每個實例都應該登錄與記錄器本身名稱相同的文件。Python記錄器動態文件名

例如爲:

log_hm = logging.getLogger('healthmonitor') 
log_hm.info("Testing Log") # Should log to /some/path/healthmonitor.log 

log_sc = logging.getLogger('scripts') 
log_sc.debug("Testing Scripts") # Should log to /some/path/scripts.log 

log_cr = logging.getLogger('cron') 
log_cr.info("Testing cron") # Should log to /some/path/cron.log 

我想保留它通用的,不想硬編碼的所有類型的記錄器的名字,我可以有。那可能嗎?

回答

7
import os 
import logging 

class MyFileHandler(object): 

    def __init__(self, dir, logger, handlerFactory, **kw): 
     kw['filename'] = os.path.join(dir, logger.name) 
     self._handler = handlerFactory(**kw) 

    def __getattr__(self, n): 
     if hasattr(self._handler, n): 
      return getattr(self._handler, n) 
     raise AttributeError, n 

logger = logging.getLogger('test') 
logger.setLevel(logging.INFO) 
handler = MyFileHandler(os.curdir, logger, logging.FileHandler) 
logger.addHandler(handler) 
logger.info('hello mylogger') 
+0

是否可以在「getLogger」調用之前添加處理程序,以便每次調用getLogger時都不必添加它? – sharjeel 2010-05-03 10:12:45

+1

@sharjeel:在初始化期間設置處理程序,以後所有對'getLogger()'的調用都不需要添加處理程序。解決方案與〜unutbu的類似。在那個例子中'myLogger'應該只被調用一次,否則你會產生奇怪的副作用。 – 2010-05-03 10:39:00

+0

我喜歡這種方法。您還可以跟蹤打開的文件和新的實例,檢查文件是否已經打開,然後不要重新打開。 雖然,在我的情況下,這種科學不是必需的:-) – sharjeel 2010-05-07 14:26:19

13

如何簡單地包裹處理程序代碼中的函數:

import os 
def myLogger(name): 
    logger = logging.getLogger(name) 
    logger.setLevel(logging.DEBUG) 
    handler = logging.FileHandler(os.path.join('/some/path/', name + '.log'), 'w') 
    logger.addHandler(handler) 
    return logger 

log_hm = myLogger('healthmonitor') 
log_hm.info("Testing Log") # Should log to /some/path/healthmonitor.log 
+1

這是一個可行的解決方案,但我正在尋找更多的Pythonic。 有沒有辦法利用現有的Python日誌框架,而不是在其上添加包裝? – sharjeel 2010-05-02 17:14:30

+0

這種方法存在問題。當使用相同名稱多次調用時,它會添加重複處理程序。打開文件是寫模式將消除以前的數據。 – 2017-09-11 23:02:25

+0

我的烤麪包機也有問題,因爲我每次烤麪包兩次,都不會像第一次烤麪包一樣。 :) – unutbu 2017-09-12 01:28:29

0

該方法在上述溶液中使用的是正確的,但有當調用多次添加重複處理的問題。這是改進版本。

import os 
def getLogger(name): 
    # logger.getLogger returns the cached logger when called multiple times 
    # logger.Logger created a new one every time and that avoids adding 
    # duplicate handlers 
    logger = logging.Logger(name) 
    logger.setLevel(logging.DEBUG) 
    handler = logging.FileHandler(os.path.join('/some/path/', name + '.log'), 'a') 
    logger.addHandler(handler) 
    return logger 

def test(i): 
    log_hm = getLogger('healthmonitor') 
    log_hm.info("Testing Log %s", i) # Should log to /some/path/healthmonitor.log 

test(1) 
test(2)