2010-05-02 18 views
5

Ich möchte meinen Python Logger so konfigurieren, dass jede Instanz des Loggers eine Datei mit demselben Namen wie der Name des Loggers selbst anmeldet.Python Logger dynamischer Dateiname

z.B .:

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 

ich möchte es halten Generika und nicht wollen, alle Arten von Logger Namen codieren kann ich. Ist das möglich?

Antwort

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

Könnte es möglich sein, den Handler vor dem Aufruf "getLogger" hinzuzufügen, so dass ich ihn nicht jedes Mal addieren muss, wenn ich getLogger anrufe? – sharjeel

+1

@sharjeel: Setzen Sie den Handler während der Initialisierung und alle zukünftigen Aufrufe von 'getLogger()' müssen keinen Handler hinzufügen. Die Lösung ähnelt der von ~ unutbu. In diesem Beispiel sollte 'myLogger' nur einmal für die Datei aufgerufen werden, sonst haben Sie seltsame Nebenwirkungen. –

+0

Ich mag diesen Ansatz. Sie können auch verfolgen, welche Dateien geöffnet sind, und bei einer neuen Instanz prüfen, ob die Datei bereits geöffnet ist, und sie nicht erneut öffnen. Obwohl solche Art von Wissenschaft in meinem Fall nicht erforderlich ist :-) – sharjeel

13

Wie wäre es einfach wickeln Sie den Handler-Code in einer Funktion:

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

Dies ist eine praktikable Lösung, aber ich bin auf der Suche nach etwas mehr Pythonic. Könnte es eine Möglichkeit geben, das vorhandene Python-Protokollierungs-Framework zu nutzen, anstatt einen Wrapper hinzuzufügen? – sharjeel

+0

Es gibt ein Problem mit diesem Ansatz. Es fügt doppelte Handler hinzu, wenn es mehrmals mit demselben Namen aufgerufen wird. Und das Öffnen der Datei ist der Schreibmodus, der die früheren Daten löscht. –

+0

Da ist auch etwas mit meinem Toaster nicht in Ordnung, denn jedes Mal, wenn ich zweimal Toast mache, kommen sie nicht wie beim ersten Mal raus. :) – unutbu

0

Der Ansatz in der obigen Lösung verwendet wird, ist richtig, aber das hat Frage der Zugabe doppelte Handler, wenn mehr als einmal aufgerufen. Hier ist die verbesserte Version.

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) 
Verwandte Themen