Ich verwende die Python-Protokollierung und aus irgendeinem Grund werden alle meine Nachrichten zweimal angezeigt.
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 auf, um die Protokollierung zu konfigurieren:
if __name__ == '__main__':
tom = Boy()
tom.configure_logging(LOG_FILENAME)
tom.buy_ham()
Und dann würde ich innerhalb des buy_ham-Moduls Folgendes nennen:
self.logger.info('Successfully able to write to %s' % path)
Aus irgendeinem Grund werden alle Nachrichten zweimal angezeigt. Ich habe einen der Stream-Handler auskommentiert, immer noch dasselbe. Etwas seltsam, nicht sicher, warum das passiert ... lol. Vorausgesetzt, ich habe etwas Offensichtliches verpasst.
Prost, Victor
configure_logging()
nicht zweimal aufgerufen wird (zB auch vom Konstruktor)? Wird nur eine Instanz von Boy () erstellt?self.logger.handlers = [ch]
stattdessen würde dieses Problem lösen, obwohl es am besten ist, nur sicherzustellen, dass Sie diesen Code nicht zweimal ausführen, indem Sie ihn beispielsweiseif not self.logger
zu Beginn verwenden.Antworten:
Sie rufen
configure_logging
zweimal auf (möglicherweise in der__init__
Methode vonBoy
):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 entfernen. Oder richten Sie ein Flag ein
logging_initialized
, dasFalse
in der__init__
Methode von initialisiert wurde,Boy
und ändern Sie esconfigure_logging
, um nichts zu tun, wenn dies der Falllogging_initialized
istTrue
, und setzen Sie es auf,True
nachdem Sie den Logger initialisiert haben.Wenn Ihr Programm mehrere
Boy
Instanzen erstellt, müssen Sie die Vorgehensweise mit einer globalenconfigure_logging
Funktion ändern, die die Handler hinzufügt, und dieBoy.configure_logging
Methode, die nur dasself.logger
Attribut initialisiert .Eine andere Möglichkeit, dies zu lösen, besteht darin, das Handler-Attribut Ihres Loggers zu überprüfen:
quelle
logger
Variable nicht die aus einer meiner Klassen instanziierte war, sondern dielogger
im Python3-Cache vorhandene Variable und der Handler wurde alle 60 Sekunden von einem von mir konfigurierten AppScheduler hinzugefügt. Diesif not logger.handlers
ist also ein ziemlich kluger Weg, um diese Art von Phänomen zu vermeiden. Danke für die Lösung, Genosse :)!Wenn Sie dieses Problem sehen und Sie hinzufügen nicht den Handler zweimal dann sehen abarnert Antwort hier
Aus den Dokumenten :
Wenn Sie also einen benutzerdefinierten Handler für "Test" möchten und nicht möchten, dass seine Nachrichten auch an den Root-Handler gesendet werden, ist die Antwort einfach: Deaktivieren Sie das Propagierungsflag:
logger.propagate = False
quelle
Der Handler wird jedes Mal hinzugefügt, wenn Sie von außerhalb anrufen. Versuchen Sie, den Handler zu entfernen, nachdem Sie Ihre Arbeit beendet haben:
quelle
logger.handlers.pop()
in Python 2.7 verwendet, macht den TrickIch bin ein Python-Neuling, aber das schien für mich zu funktionieren (Python 2.7)
quelle
In meinem Fall würde ich festlegen
logger.propagate = False
, um Doppeldruck zu verhindern.Wenn Sie im folgenden Code entfernen
logger.propagate = False
, wird der Doppeldruck angezeigt.quelle
logger.propagate = False
war die Lösung, um eine doppelte Protokollierung in einer von Waitress gehosteten Flask-Anwendung zu verhindern, wenn Sie sich bei der Flask-app.logger
Instanz anmelden .Ein Aufruf zum
logging.debug()
Aufrufen,logging.basicConfig()
wenn keine Root-Handler installiert sind. Das geschah für mich in einem Test-Framework, in dem ich die Reihenfolge, in der Testfälle ausgelöst wurden, nicht kontrollieren konnte. Mein Initialisierungscode war die Installation des zweiten. Die Standardeinstellung verwendet logging.BASIC_FORMAT, die ich nicht wollte.quelle
Es scheint, dass es zu spät ist, wenn Sie etwas (versehentlich) an den Logger ausgeben und dann konfigurieren. Zum Beispiel in meinem Code hatte ich
Ich würde so etwas bekommen (die Formatoptionen ignorieren)
und alles wurde zweimal auf stdout geschrieben. Ich glaube, das liegt daran, dass beim ersten Aufruf
logging.warning
automatisch ein neuer Handler erstellt wird und ich dann explizit einen weiteren Handler hinzugefügt habe. Das Problem verschwand, als ich den versehentlichen erstenlogging.warning
Anruf entfernte.quelle
Ich hatte eine seltsame Situation, in der Konsolenprotokolle verdoppelt wurden, meine Dateiprotokolle jedoch nicht. Nach einer Menge Graben habe ich es herausgefunden.
Bitte beachten Sie, dass Pakete von Drittanbietern Logger registrieren können. Dies ist etwas, auf das Sie achten müssen (und das in einigen Fällen nicht verhindert werden kann). In vielen Fällen überprüft der Code von Drittanbietern, ob Root- Logger-Handler vorhanden sind. und wenn nicht, registrieren sie einen neuen Konsolenhandler.
Meine Lösung bestand darin, meinen Konsolenlogger auf der Stammebene zu registrieren:
quelle