2010-05-02 19 views
5

Chcę skonfigurować mój logger Pythona w taki sposób, aby każda instancja rejestratora logowała się do pliku o takiej samej nazwie jak nazwa samego rejestratora.Python logger dynamiczna nazwa pliku

np .:

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 

chcę zachować ogólny i nie chcesz hardcode wszelkiego rodzaju nazw rejestratora mogę mieć. Czy to jest możliwe?

Odpowiedz

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

Czy możliwe jest dodanie handler'a przed wywołaniem "getLogger", więc nie muszę go dodawać za każdym razem, gdy dzwonię do getLoggera? – sharjeel

+1

@sharjeel: Ustaw program obsługi podczas inicjowania i wszystkie przyszłe wywołania funkcji 'getLogger()' nie muszą dodawać procedury obsługi. Rozwiązanie jest podobne do rozwiązania ~ unutbu. W tym przykładzie 'mójLogger' powinien być wywołany tylko raz dla pliku, w przeciwnym razie wystąpią dziwne efekty uboczne. –

+0

Podoba mi się to podejście. Możesz również zachować ścieżkę otwartych plików i nowej instancji, sprawdzić, czy plik jest już otwarty, a następnie nie otwierać ponownie. Jednak taka nauka nie jest wymagana w moim przypadku :-) – sharjeel

13

Jak o po prostu zawinąć kod obsługi w funkcji:

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

Jest to wykonalne rozwiązanie, ale szukam czegoś bardziej Pythonicznego. Czy istnieje sposób na wykorzystanie istniejącego środowiska logowania w języku Python, zamiast dodawania otoki na nim? – sharjeel

+0

Występuje problem z tym podejściem. Dodaje zduplikowane procedury obsługi po wywołaniu więcej niż raz o tej samej nazwie. Otwieranie pliku to tryb zapisu, który usunie wcześniejsze dane. –

+0

Jest też coś nie tak z moim tosterem, ponieważ za każdym razem, kiedy wznosiłem toast dwa razy, nie wychodzi po raz pierwszy. :) – unutbu

0

Podejście stosowane w powyższym roztworze jest poprawne, ale to nie ma problemu dodawania duplikaty teleskopowe gdy wywoływany więcej niż raz. Oto ulepszona wersja.

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) 
Powiązane problemy