2009-05-18 1 views
24

Ich verwende Protokollierung (Protokollierung importieren), um Nachrichten zu protokollieren.Protokollierung mit Filtern

Innerhalb von einem einzigen Modul protokolliere ich Nachrichten auf der Debug-Ebene (my_logger.debug ('msg'));

Einige dieser Debug-Meldungen stammen von function_a() und andere von function_b(); Ich möchte die Protokollierung aktivieren/deaktivieren basierend darauf, ob sie von einem oder von b kommen;

Ich vermute, dass ich Logging-Filter-Mechanismus verwenden muss.

Kann mir bitte jemand zeigen, wie der unten stehende Code instrumentiert werden müsste, um das zu tun, was ich will? Vielen Dank.

import logging 
logger= logging.getLogger("module_name") 

def function_a(...): 
    logger.debug("a message") 

def function_b(...): 
    logger.debug("another message") 

if __name__ == "__main__": 
    logging.basicConfig(stream=sys.stderr, level=logging.DEBUG) 

    #don't want function_a()'s noise -> .... 
    #somehow filter-out function_a's logging 
    function_a() 

    #don't want function_b()'s noise -> .... 
    #somehow filter-out function_b's logging 
    function_b() 

Wenn ich dieses einfache Beispiel, um weitere Module skaliert und mehr funcs pro Modul, würde ich über viele Loggern betroffen sein;

Kann ich es auf 1 Logger pro Modul beschränken? Beachten Sie, dass die Log-Nachrichten "strukturiert" sind, dh wenn die Logging-Funktion einige Parsing-Arbeiten durchführt, enthalten sie alle ein Präfix logger.debug ("parsing: xxx") - kann ich irgendwie mit einer einzelnen Zeile einfach schließen - alle "Parsing" -Nachrichten abbrechen (unabhängig von dem Modul/der Funktion, die die Nachricht ausgibt?)

Antwort

36

implementieren einfach eine Unterklasse von logging.Filter: http://docs.python.org/library/logging.html#filter-objects. Es wird eine Methode haben, filter(record), die den Protokolleintrag überprüft und True zurückgibt, um es zu protokollieren, oder False, um es zu verwerfen. Dann können Sie den Filter entweder auf Logger oder Handler durch den Aufruf seiner Methode installieren.

Beispiel:

class NoParsingFilter(logging.Filter): 
    def filter(self, record): 
     return not record.getMessage().startswith('parsing') 

logger.addFilter(NoParsingFilter()) 

Oder so ähnlich jedenfalls.

+6

Ich musste den Filter zum Handler hinzufügen. –

15

Nicht global verwenden. Es ist ein Unfall, der darauf wartet, passiert zu sein.

Sie können Ihren Loggern beliebige "." - getrennte Namen geben, die für Sie von Bedeutung sind.

Sie können sie als Hierarchie steuern. Wenn Sie über Protokollierer mit den Namen a.b.c und a.b.d verfügen, können Sie den Protokolliergrad für a.b überprüfen und beide Protokollierer ändern.

Sie können beliebig viele Logger verwenden - sie sind kostengünstig.

Das am häufigsten verwendete Designmuster ist ein Logger pro Modul. Siehe Naming Python loggers

Tun Sie dies.

import logging 

logger= logging.getLogger("module_name") 
logger_a = logger.getLogger("module_name.function_a") 
logger_b = logger.getLogger("module_name.function_b") 

def function_a(...): 
    logger_a.debug("a message") 

def functio_b(...): 
    logger_b.debug("another message") 

if __name__ == "__main__": 
    logging.basicConfig(stream=sys.stderr, level=logging.DEBUG) 
    logger_a.setLevel(logging.DEBUG) 
    logger_b.setLevel(logging.WARN) 

    ... etc ... 
+1

danke S.Lott für Ihre Antwort; das würde funktionieren; Wenn ich jedoch mein einfaches Beispiel auf mehr Module und mehr Funktionen pro Modul skalieren würde, wäre ich über viele Logger besorgt; Kann ich es auf 1 Logger pro Modul beschränken? Beachten Sie, dass die Log-Nachrichten "strukturiert" sind, dh wenn die Funktion (en), die sie protokollieren, einige Parsing-Arbeiten durchführen, enthalten sie alle ein Präfix logger.debug ("parsing: ...") - kann ich irgendwie mit einer einzelnen Zeile einfach alle "Parsing" -Nachrichten abschalten (unabhängig von dem Modul/der Funktion, die die Nachricht ausgibt?) –