it-swarm.com.de

protokollnachrichten, die zweimal mit Python Logging angezeigt werden

Ich verwende die Python-Protokollierung, und aus irgendeinem Grund erscheinen alle meine Nachrichten zweimal.

Ich habe ein Modul zum Konfigurieren der Protokollierung:

# BUG: It's outputting logging messages twice - not sure why - it's not the propagate setting.
def configure_logging(self, logging_file):
    self.logger = logging.getLogger("my_logger")
    self.logger.setLevel(logging.DEBUG)
    self.logger.propagate = 0
    # Format for our loglines
    formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
    # Setup console logging
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    ch.setFormatter(formatter)
    self.logger.addHandler(ch)
    # Setup file logging as well
    fh = logging.FileHandler(LOG_FILENAME)
    fh.setLevel(logging.DEBUG)
    fh.setFormatter(formatter)
    self.logger.addHandler(fh)

Später rufe ich diese Methode zur Konfiguration der Protokollierung auf:

if __== '__main__':
    tom = Boy()
    tom.configure_logging(LOG_FILENAME)
    tom.buy_ham()

Und dann innerhalb von say, dem Modul buy_ham, würde ich Folgendes nennen:

self.logger.info('Successfully able to write to %s' % path)

Und aus irgendeinem Grund erscheinen alle Nachrichten zweimal. Ich kommentierte einen der Stream-Handler aus, immer noch dasselbe. Etwas seltsam, nicht sicher, warum das passiert ... lol. Angenommen, ich habe etwas offensichtlich übersehen.

Prost, Victor

61
victorhooi

Sie rufen zweimal configure_logging auf (möglicherweise in der __init__-Methode von Boy): getLogger gibt dasselbe Objekt zurück, addHandler prüft jedoch nicht, ob dem Logger bereits ein ähnlicher Handler hinzugefügt wurde. 

Versuchen Sie, Aufrufe dieser Methode zu verfolgen und eine davon zu eliminieren. Oder setzen Sie ein Flag logging_initialized, das in der __init__-Methode von False auf Boy initialisiert ist, und ändern Sie configure_logging, um nichts zu tun, wenn logging_initializedTrue ist, und nachdem Sie den Logger initialisiert haben, auf True zu setzen. 

Wenn Ihr Programm mehrere Boy-Instanzen erstellt, müssen Sie die Vorgehensweise ändern, indem Sie eine globale configure_logging-Funktion hinzufügen, die die Handler hinzufügt, und die Boy.configure_logging-Methode nur das self.logger-Attribut initialisiert.

Eine andere Möglichkeit, dies zu lösen, besteht darin, das Handler-Attribut Ihres Loggers zu überprüfen:

logger = logging.getLogger('my_logger')
if not logger.handlers:
    # create the handlers and call logger.addHandler(logging_handler)
88
gurney alex

Der Handler wird bei jedem Anruf von außen hinzugefügt. Versuchen Sie, den Handler zu entfernen, nachdem Sie Ihre Arbeit beendet haben:

self.logger.removeHandler(ch)
6
Mayukh Roy

Ich bin ein Python-Neuling, aber das schien für mich zu funktionieren (Python 2.7)

while logger.handlers:
     logger.handlers.pop()
5
Gregory Ponto

Wenn Sie dieses Problem sehen und den Handler nicht zweimal hinzufügen, dann sehen Sie die Antwort von abarnert hier

Aus den docs :

Hinweis: Wenn Sie einen Handler an einen Logger und einen oder mehrere seiner .__ anhängen. Vorfahren kann derselbe Datensatz mehrmals ausgegeben werden. Im Allgemeinen haben Sie Sie müssen keinen Handler an mehr als einen Logger anschließen - wenn Sie Verbinden Sie es einfach mit dem entsprechenden Logger, der im .__ am höchsten ist. Logger-Hierarchie, dann werden alle Ereignisse angezeigt, die von allen Nachkommen protokolliert werden Logger, vorausgesetzt, ihre Weitergabeeinstellung bleibt auf True gesetzt. EIN Das übliche Szenario besteht darin, Handler nur an den Root-Logger und an .__ anzuhängen. Die Ausbreitung kümmert sich um den Rest.

Wenn Sie also einen benutzerdefinierten Handler auf "test" setzen möchten und nicht möchten, dass die Nachrichten auch an den Root-Handler gesendet werden, ist die Antwort einfach: Deaktivieren Sie das Propagierungsflag:

logger.propagate = False

5

Ein Aufruf von logging.debug() ruft logging.basicConfig() auf, wenn keine Root-Handler installiert sind. Dies geschah für mich in einem Testrahmen, in dem ich nicht die Reihenfolge kontrollieren konnte, in der Testfälle ausgelöst wurden. Mein Initialisierungscode war die Installation des zweiten. Die Standardeinstellung verwendet die Protokollierung.BASIC_FORMAT, die ich nicht wollte.

0
JimB