Ich benutze Python Logger. Folgendes ist mein Code:
import os
import time
import datetime
import logging
class Logger :
def myLogger(self):
logger = logging.getLogger('ProvisioningPython')
logger.setLevel(logging.DEBUG)
now = datetime.datetime.now()
handler=logging.FileHandler('/root/credentials/Logs/ProvisioningPython'+ now.strftime("%Y-%m-%d") +'.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
return logger
Das Problem ist, dass ich für jeden logger.info
Anruf mehrere Einträge in der Protokolldatei erhalte . Wie kann ich das lösen?
Antworten:
Das
logging.getLogger()
ist schon ein Singleton. ( Dokumentation )Das Problem ist, dass bei jedem Aufruf
myLogger()
der Instanz ein weiterer Handler hinzugefügt wird, der zu doppelten Protokollen führt.Vielleicht so etwas?
quelle
loggers.update(dict(name=logger))
? ist nichtloggers[name] = logger
einfacher?loggers.update(dict(name=logger))
erstellt ein Wörterbuch mit einem einzelnen Schlüsselname
und aktualisiert diesen Schlüssel kontinuierlich. Ich bin überrascht, dass dies niemand zuvor erwähnt hat, da dieser Code ziemlich kaputt ist :) Wird die erforderlichen Änderungen vornehmen.loggers
Wörterbuch nicht redundantlogging.getLogger
? Da Sie wirklich nur vermeiden möchten, zusätzliche Handler hinzuzufügen, scheinen Sie die Antworten unten zu bevorzugen, die direkt nachSeit Python 3.2 können Sie einfach überprüfen, ob bereits Handler vorhanden sind, und diese in diesem Fall löschen, bevor Sie neue Handler hinzufügen. Dies ist beim Debuggen sehr praktisch und der Code enthält Ihre Logger-Initialisierung
quelle
machte den Trick für mich
mit Python 2.7
quelle
Ich habe das bereits
logger
als Singleton verwendet und überprüftif not len(logger.handlers)
, aber immer noch Duplikate erhalten : Es war die formatierte Ausgabe, gefolgt von der unformatierten.Lösung in meinem Fall:
logger.propagate = False
Dank an diese Antwort und die Dokumente .
quelle
Sie rufen
Logger.myLogger()
mehr als einmal an. Speichern Sie die Logger - Instanz es gibt irgendwo und Wiederverwendung , dass .Beachten Sie außerdem, dass ein Standardwert erstellt
StreamHandler(sys.stderr)
wird , wenn Sie sich vor dem Hinzufügen eines Handlers anmelden .quelle
Dies ist eine Ergänzung zu @ rm957377s Antwort, aber mit einer Erklärung, warum dies geschieht . Wenn Sie eine Lambda-Funktion in AWS ausführen, rufen sie Ihre Funktion innerhalb einer Wrapping-Instanz auf, die für mehrere Aufrufe am Leben bleibt. Das heißt, wenn Sie
addHandler()
den Code Ihrer Funktion aufrufen , werden dem Protokollierungs-Singleton bei jeder Ausführung der Funktion weiterhin doppelte Handler hinzugefügt. Der Protokollierungs-Singleton bleibt durch mehrere Aufrufe Ihrer Lambda-Funktion bestehen.Um dies zu lösen, können Sie Ihre Handler löschen, bevor Sie sie einstellen über:
quelle
.info()
Abruf hinzugefügt , was ich nicht verstehe.Ihr Logger sollte als Singleton arbeiten. Sie sollten es nicht mehr als einmal erstellen. Hier ist ein Beispiel, wie es aussehen könnte:
quelle
Die Implementierung von Logger ist bereits ein Singleton.
Quelle - Verwenden der Anmeldung in mehreren Modulen
Die Art und Weise, wie Sie dies nutzen sollten, ist -
Nehmen wir an, wir haben im Hauptmodul einen Logger namens 'main_logger' erstellt und konfiguriert (der den Logger einfach konfiguriert und nichts zurückgibt ).
Wenn wir jetzt in einem Untermodul einen untergeordneten Logger erstellen , der der Namenshierarchie 'main_logger.sub_module_logger' folgt, müssen wir ihn nicht im Untermodul konfigurieren. Es reicht aus, nur den Logger nach der Namenshierarchie zu erstellen.
Außerdem wird kein doppelter Handler hinzugefügt.
In dieser Frage finden Sie eine ausführlichere Antwort.
quelle
logger = logging.getLogger('my_logger') ; logger.handlers = [logger.handlers[0], ]
Eine doppelte (oder dreifache oder ..- basierend auf der Anzahl der Neuladungen) Logger-Ausgabe kann auch auftreten, wenn Sie Ihr Modul über neu laden
importlib.reload
(aus dem gleichen Grund, wie in der akzeptierten Antwort erläutert). Ich füge diese Antwort nur als zukünftige Referenz hinzu, da ich eine Weile gebraucht habe, um herauszufinden, warum meine Ausgabe doppelt (dreifach) ist.quelle
Eine einfache Problemumgehung ist wie
Auf diese Weise vermeiden Sie, dass ein neuer Handler an die zugrunde liegende Liste "Handler" angehängt wird.
quelle
Fazit: In den meisten Fällen muss logger.getLogger () nur einmal pro Modul aufgerufen werden. Wenn Sie wie ich mehrere Klassen haben, könnte ich das so nennen:
Beide haben dann ihren eigenen vollständigen Paketnamen und ihre eigene Methode, wo sie protokolliert werden.
quelle
Sie können eine Liste aller Handler für den jeweiligen Logger abrufen, um so etwas zu tun
Im obigen Beispiel prüfen wir, ob der Handler für eine angegebene Datei bereits mit dem Logger verknüpft ist. Wenn Sie jedoch auf die Liste aller Handler zugreifen können, können Sie entscheiden, nach welchen Kriterien Sie einen weiteren Handler hinzufügen möchten oder nicht.
quelle
Hatte heute dieses Problem. Da meine Funktionen @staticmethod waren, wurden die obigen Vorschläge mit random () aufgelöst.
Sieht ungefähr so aus:
quelle
quelle