logging zentral ausstellen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Boa
User
Beiträge: 190
Registriert: Sonntag 25. Januar 2009, 12:34

Hallo,

Ich hatte vor längerer Zeit die gleiche Frage, aber dann die Geduld verloren mich weiter damit zu beschäftigen. Der alte Thread dazu ist: http://www.python-forum.de/viewtopic.php?f=1&t=27264

Ich fasse die Ergebnisse noch Mal zusammen und beschreibe mein Problem mit ein paar Ergänzungen. Ich verwende Python 2.6. Das Logging für mehrere Module soll zentral über die log.conf gesteuert werden. Meine Frage ist, ob und wie man über die log.conf das Logging auf einfache Weise ausstellen kann. Eine Möglichkeit, die genannt wurde ist das Hochsetzen der Warn-Levels. Dadurch wird aber das Logging nicht ausgestellt und vermutlich werden die Dateien für das Logging weiterhin erzeugt. Auch wenn es keine direkt Antwort auf meine Frage war, sollte eine weitere Möglichkeit sein in der __main__ folgenden Code einzubauen:

Code: Alles auswählen

class NullHandler(logging.Handler):
    def emit(self, *args, **kwargs):
        pass
logging.getLogger().addHandler(NullHandler())
Allerdings wird das Logging dadurch in meinem Fall nicht ausgeschaltet.
Es wurde behauptet, dass das mehrfache Ausführen von fileConfig falsch ist. In der Dokumentation steht jedoch "This function can be called several times from an application". http://docs.python.org/library/logging. ... fileConfig

Logger deren Namen durch Punkte getrennt werden können so hierarchisch behandelt werden. Ich habe mir gedacht, ob man in der Konfigurationsdatei vielleicht die Logger als root, root.modul1, root.module1.modulsub angeben kann und dadurch irgendwie das ausschalten des Loggings vereinfachen kann.

Ich hoffe ich habe nun bereits etwas mehr Einsicht ins Logging gewonnen und bitte darum dass ihr mir erneut helft diese zu erweitern.

MfG,
Boa
deets

Offensichtlich kann man jetzt das fileConfig mehrfach aufrufen, weil da jetzt ein extra Parameter bekommen hat. Aber das aendernt nichts von dem, was ich in dem ander Thread gesagt habe: code, der fuer die Benutzung durch andere gedacht ist, sollte

- den NullHandler installieren, um keine Warnungen zu generieren
- *NIEMALS* selbst das Logging konfigurieren.

Punkt.

Wenn du deinen Code dann testen/debuggen willst, dann ruf ihn durch ein Testskript auf, bzw. innerhalb eines __name__ == "__main__"-Blocks.
Boa
User
Beiträge: 190
Registriert: Sonntag 25. Januar 2009, 12:34

deets hat geschrieben:Offensichtlich kann man jetzt das fileConfig mehrfach aufrufen, weil da jetzt ein extra Parameter bekommen hat.
Ah, dann heißt der neue Parameter also, dass er den vorherigen Aufruf von fileConfig ungültig machen kann, aber im Prinzip der einmalige Aufruf genügt.
deets hat geschrieben:Aber das aendernt nichts von dem, was ich in dem ander Thread gesagt habe: code, der fuer die Benutzung durch andere gedacht ist, sollte

- den NullHandler installieren, um keine Warnungen zu generieren
- *NIEMALS* selbst das Logging konfigurieren.

Punkt.

Wenn du deinen Code dann testen/debuggen willst, dann ruf ihn durch ein Testskript auf, bzw. innerhalb eines __name__ == "__main__"-Blocks.
Ok, wie ich es jetzt verstanden habe machte es Sinn. Mit man sollte niemals selbst das Logging konfigurieren meinst du, dass man das Logging standardmäßig ausstellen soll, was ja genau das Ziel ist, dass ich versuche zu erreichen. Nur kam mir deine Formulierung unverständlich vor, da man das setzen des NullHandlers oder andere Maßnahmen zur Deaktivierund des Loggings durchaus als Konfiguration dessen verstehen kann. So, da ich jetzt weiß, dass durch fileConfig die vorherige Konfiguration aufgehoben wird, werde ich versuchen diese Aufrufe aus allen Modulen zu entfernen, im main Module den NullHandler zu setzen und noch einen Parameter einführen, mit dem man das Logging gemäß der Konfigurationsdatei einfach einschalten kann, indem der NullhHandler nicht gesetzt wird und stattdessen einmalig fileConfig ausgeführt wird.

Wäre das soweit richtig?
deets

Nein, nicht richtig. Den NullHandler in den *Modulen* die du distributierst definieren & setzen. Nehmen wir mal an, du hast ein Modul foo.py, dass du weiter gibst:

Code: Alles auswählen

# foo.py
import logging

logger = logging.getLogger(__name__)

def tuwas():
      logger.errror("tuwas")
Koennte natuerlich auch ein Package sein, das ist jetzt irrelevant. Wenn du dieses Modul jetzt weitergibst, und irgendwer, der von logging keine Ahnung hat & den es auch nicht kuemmert benutzt das jetzt - dann bekommt der die "no handlers could be found for logger foo"-Ausgabe.

Also musst du in jedem Modul den NullHandler setzen. Und zur Not auch neu definieren (die Klasse) - aber das macht ja nix. Es ist natuerlich etwas doof, dass das System sich so verhaelt. Aber ist halt so.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@Boa: Ein Setzen des `NullHandlers` bedeutet ja erstmal nur, dass der eigene Logger die eingegangenen Meldungen nicht weiter behandelt. Diese werden dann aber AFAIK an den nächsthöheren Logger gereicht. Will man das Logging wirklich komplett ausschalten, so muss man das in einer zentralen Datei regeln. Ich habe vor circa einem Monat zu dem Thema etwas gepostet. Vielleicht entspricht diese "Lösung" ja dem, was du dir vorgestellt hast. :)

Beachte dort auch die Verlinkung zum Code. Ich mache einfach eine `if logger is not None`-Prüfung, bevor ich logge. Diese modifizierte Version wird dann von meinen Funktion (`info()`, `debug()`, usw) auf Modulebene genutzt.
deets

@snafu

Nein, der NullHandler reicht voellig. Muss natuerlich auf den root-logger gesetzt werden.
Boa
User
Beiträge: 190
Registriert: Sonntag 25. Januar 2009, 12:34

deets hat geschrieben:Koennte natuerlich auch ein Package sein, das ist jetzt irrelevant. Wenn du dieses Modul jetzt weitergibst, und irgendwer, der von logging keine Ahnung hat & den es auch nicht kuemmert benutzt das jetzt - dann bekommt der die "no handlers could be found for logger foo"-Ausgabe.

Also musst du in jedem Modul den NullHandler setzen. Und zur Not auch neu definieren (die Klasse) - aber das macht ja nix. Es ist natuerlich etwas doof, dass das System sich so verhaelt. Aber ist halt so.
Nach dem Beispiel hat es Klick gemacht. Aus der Perspektive eines Entwicklers, der auf die Schnittstelle einzelner Module zugreifen will anstatt wie der Endnutzer die Schnittstelle der ganzen Komponente zu nutzen macht das natürlich Sinn. An dieses Szenario hatte ich nicht gedacht, da ich mein Programm immer als Komponente betrachtet hatte. Aber im Prinzip lassen sich Teile davon duchaus als Library verwenden. Wenn man nicht die Komponenten Schnittstelle verwendet, die von Linux abhängig ist, sollte der Code damit sogar auf Windows lauffähig sein.

Vielen Dank für deine Hilfe. Du hast mir sehr weitergeholfen.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

deets hat geschrieben:Nein, der NullHandler reicht voellig. Muss natuerlich auf den root-logger gesetzt werden.
Logging ist aber IMHO als *globale* Sache zu sehen. Wenn das Logging für's eigene Package ausgeschaltet werden soll, dann muss dies nicht unbedingt bedeuten, dass ich *alles* an Logging für die gesamte Session des Python-Interpreters ausschalten möchte. Ist sicher Ansichtssache, inwiefern das ein realistischer Use-Case ist. Ich fänd einen `NullHandler` auf dem Root-Logger halt unsauber. Es wäre IMHO durchaus praktisch, wenn das API des `logging`-Moduls für ein Logger-Exemplar eine Art `disable`-Methode anbieten würde - tut es aber nicht.
deets

@snafu

ich verstehe deinen Post nicht. Verstehst du, was der NullHandler tut? Alles worum es dabei geht ist, einen *Fehler* in der 2.x-er Version des logging-Moduls zu korrigieren - naemlich die Ausgabe von "no handler found for ..." messages. Das ist alles. Das ist unsauber, weil das logging-Modul unsauber ist. Aber so ist es nunmal.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@deets: Ich habe dem `NullLogger` auch keine weiteren Fähigkeiten zugesprochen, außer dass er eben jegliche Ausgabe unterdrückt. Was ich meinte, ist Folgendes: Denken wir uns mal zwei Bibliotheken: `pkg1` und `pkg2`. Beide betreiben Logging. `pkg1` benutzt einen eigenen Logger, `pkg2` schreibt auf dem Root-Logger. Jetzt sollen alle Log-Messages von `pkg1` unterdrückt werden und die Meldungen von `pkg2` sollen weiter ersichtlich sein. `pkg1` wendet also (nachdem der Benutzer dafür eine bereitgestelle Funktion aufgerufen hat) den `NullLogger` an. Auf dem eigenen Logger bringt es nicht viel, da die Meldungen dann hochgereicht werden. Also setzt es den `NullHandler` auf den Root-Logger. Damit hat es unweigerlich auch jegliches Logging von `pkg2` stummgeschaltet, oder irre ich mich da? Das kann doch nicht die Lösung sein...
deets

@snafu

Du irrst dich. Die Handler werden hinzugefuegt. Das ganze Konzept des NullHandlers basiert darauf, dass er nur *einer* von potentiell vielen ist. Das logging-Modul setzt halt vorraus, dass es *einen* gibt - sonst kommt der Fehler. Darum der NullHandler.

Das alles beruehrt nicht die progagation von der Logger-Hierarchie wenn kein handler gefunden wurde, noch die Konfigurierbarkeit.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@deets: Ich glaube, du verstehst nicht, worauf ich hinaus will. Du kommst wiederholt auf das "Kein-Handler-gefunden" Problem zu sprechen, um das es mir aber überhaupt nicht geht. Mir geht es um die Unterscheidung zwischen Messages von `pkg1` und `pkg2`. Meines Wissens kann der Root-Logger nicht erkennen, dass er hochgereichte Nachrichten eines bestimmten Loggers unterdrücken soll. Es geht immer nur "ganz oder garnicht". Scheinbar reden wir hier aber aneinander vorbei...
deets

@snafu

Offensichtlich. Darum nochmal: dein Szenario wird von dem NullHandler nicht beruehrt. Der NullHandler beruehrt kein einziges feature des logging Systems. Seine Auswirkungen zeigt er *NUR* dann, wenn das System eben *NICHT* konfiguriert wurde in irgend einer Form. Ob, wann, wie und wo Nachrichten von pkg1 und pkg2 von dem root-logger verarztet werden hat damit nichts zu tun.

Dein Aussage
Also setzt es den `NullHandler` auf den Root-Logger. Damit hat es unweigerlich auch jegliches Logging von `pkg2` stummgeschaltet, oder irre ich mich da? Das kann doch nicht die Lösung sein...
stimmt also nicht. Der NullHandler schaltet nichts stumm. Er unterdrueckt einzig und alleine die Fehlermeldung.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

deets hat geschrieben:Der NullHandler schaltet nichts stumm. Er unterdrueckt einzig und alleine die Fehlermeldung.
Ahhh, okay. Dessen war ich mir tatsächlich nicht bewusst. Deshalb heißt er wahrscheinlich auch `NullHandler` und nicht `MuteHandler` oder so. Danke für die Erleuchtung. ;)

Ich hatte halt nicht bedacht, dass man den Handler nicht als den einzigen Handler sehen darf, der für den Logger registriert wurde. Ein Handler kommt ja einfach in die Liste der bereits registrierten Handler und hat sozusagen keine Alleingewalt über den Logger, sondern er macht einfach nur seine Aufgabe, wenn er eben "an der Reihe" ist.
Antworten