2013-04-03 8 views
9

Ich fragte mich, was die Standard-Einrichtung für die Durchführung der Protokollierung von innerhalb einer Python-App ist.Wie verwende ich Python Logging in mehreren Modulen

Ich verwende die Protokollierungsklasse, und ich habe meine eigene Protokollierungsklasse geschrieben, die die Protokollierungsklasse instanziiert. Mein Hauptprogramm instanziiert dann meine Logger-Wrapper-Klasse. Mein Hauptprogramm instanziiert jedoch andere Klassen, und ich möchte, dass diese anderen Klassen auch über das Loggerobjekt im Hauptverzeichnis in die Protokolldatei schreiben können.

Wie mache ich das Logger-Objekt so, dass es von anderen Klassen aufgerufen werden kann? Es ist fast so, als ob wir eine Art statisches Logger-Objekt benötigen, um das zu erreichen.

Ich denke, die lange und kurze der Frage ist: Wie implementieren Sie die Protokollierung innerhalb Ihrer Code-Struktur, so dass alle Klassen aus Main innerhalb der gleichen Protokolldatei geschrieben werden können? Muss ich nur ein neues Protokollierungsobjekt in jeder der Klassen erstellen, die auf dieselbe Datei verweisen?

Antwort

6

Versuchen Sie es mit logging.getLogger(), um Ihre Logging-Objekt-Instanz zu erhalten:

http://docs.python.org/3/library/logging.html#logging.getLogger

Alle Anrufe an diese Funktion mit einem bestimmten Namen, um die gleiche Logger-Instanz zurück. Dies bedeutet, dass Loggerinstanzen niemals zwischen verschiedenen Teilen einer Anwendung ausgetauscht werden müssen.

UPDATE:

Der empfohlene Weg, dies zu tun ist, um die getLogger() Funktion zu verwenden und konfigurieren (einen Handler Einstellung Formatierer, etc ...):

# main.py 
import logging 
import lib 


def main(): 
    logger = logging.getLogger('custom_logger') 
    logger.setLevel(logging.INFO) 
    logger.addHandler(logging.FileHandler('test.log')) 
    logger.info('logged from main module') 
    lib.log() 

if __name__ == '__main__': 
    main() 

# lib.py 
import logging 


def log(): 
    logger = logging.getLogger('custom_logger') 
    logger.info('logged from lib module') 

Wenn Sie wirklich benötigen die Logger-Klasse einen Blick auf logging.setLoggerClass (klass)

erweitern

UPDATE 2:

Beispiel auf, wie eine benutzerdefinierte Protokollebene hinzuzufügen, ohne die Logging-Klasse zu ändern:

# main.py 
import logging 
import lib 


# Extend Logger class 
CUSTOM_LEVEL_NUM = 9 
logging.addLevelName(CUSTOM_LEVEL_NUM, 'CUSTOM') 
def custom(self, msg, *args, **kwargs): 
    self._log(CUSTOM_LEVEL_NUM, msg, args, **kwargs) 
logging.Logger.custom = custom 

# Do global logger instance setup 
logger = logging.getLogger('custom_logger') 
logger.setLevel(logging.INFO) 
logger.addHandler(logging.FileHandler('test.log')) 


def main(): 
    logger = logging.getLogger('custom_logger') 
    logger.custom('logged from main module') 
    lib.log() 

if __name__ == '__main__': 
    main() 

Hinweis, die benutzerdefinierte Ebene hinzugefügt wird nicht empfohlen: http://docs.python.org/2/howto/logging.html#custom-levels

eine benutzerdefinierte Definition Handler und möglicherweise mit mehr als einem Logger können den Trick für Ihre andere Anforderung tun: optionale Ausgabe zu stderr.

+0

Sorry für ein wenig dicht hier .... also dann Wenn ich ein Hauptmodul habe, das meine eigene Log-Klasse instanziiert (die die Protokollierungsklasse enthält) dann ist es sicherlich einfach, Dinge durch einfaches Aufrufen meines Log-Objekts zu protokollieren. Wenn mein Hauptmodul jedoch andere Module importiert, wie kann ich einen Aufruf an meine Protokollklassenmethoden vornehmen, um zu protokollieren, ohne ein Protokollhandle an jede Methode zu übergeben? Können Sie ein Beispiel mit mehreren Modulen bereitstellen? – GregH

+0

Ich habe ein Beispiel mit mehreren Modulen und der Funktion getLogger() bereitgestellt. Es ist selten, dass Sie die Logger-Klasse (logging.getLoggerClass()) erweitern müssen, wenn Sie wirklich einen Logger mit getLogger erstellen und einen benutzerdefinierten Handler konfigurieren möchten. Formatierer ist nicht genug für Ihre Bedürfnisse. Bitte erklären Sie, was die Logger-Klasse ist. – gonz

+0

@GregH Hat mein Beispiel Sinn ergeben? Lassen Sie mich wissen, ob das Ihr Problem löst oder Sie weitere Erklärungen benötigen. – gonz

24

Ich weiß nicht, was Sie unter der Klasse Logging verstehen - es gibt keine solche Klasse in Pythons integrierter Protokollierung. Sie haben nicht wirklich Wrapper benötigen: hier ist ein Beispiel dafür, wie die Protokollierung von beliebigen Klassen zu tun, die Sie schreiben:

import logging 

# This class could be imported from a utility module 
class LogMixin(object): 
    @property 
    def logger(self): 
     name = '.'.join([__name__, self.__class__.__name__]) 
     return logging.getLogger(name) 


# This class is just there to show that you can use a mixin like LogMixin 
class Base(object): 
    pass 

# This could be in a module separate from B 
class A(Base, LogMixin): 
    def __init__(self): 
     # Example of logging from a method in one of your classes 
     self.logger.debug('Hello from A') 

# This could be in a module separate from A 
class B(Base, LogMixin): 
    def __init__(self): 
     # Another example of logging from a method in one of your classes 
     self.logger.debug('Hello from B') 

def main(): 
    # Do some work to exercise logging 
    a = A() 
    b = B() 
    with open('myapp.log') as f: 
     print('Log file contents:') 
     print(f.read()) 

if __name__ == '__main__': 
    # Configure only in your main program clause 
    logging.basicConfig(level=logging.DEBUG, 
         filename='myapp.log', filemode='w', 
         format='%(name)s %(levelname)s %(message)s') 
    main() 

Generell ist es nicht notwendig, Logger auf Klassenebene haben: in Python, im Gegensatz zu Java sagen, das Gerät Programm (de) Zusammensetzung ist das Modul. Nichts hält dich davon ab, wie ich oben gezeigt habe. Das Skript, wenn ausführen, zeigt:

Log file contents: 
__main__.A DEBUG Hello from A 
__main__.B DEBUG Hello from B 

Beachten Sie, dass Code aus beiden Klassen angemeldet auf die gleiche Datei, myapp.log.Dies hätte auch mit A und B in verschiedenen Modulen funktioniert.

+0

Dies ist die eleganteste Lösung, die ich für die Anmeldung in Python gesehen habe. Ich danke Ihnen für das Teilen :-) –

Verwandte Themen