Ich versuche zu lernen, wie eine Anwendung funktioniert. Und dafür füge ich Debug-Befehle als erste Zeile des Funktionskörpers ein, mit dem Ziel, den Namen der Funktion sowie die Zeilennummer (innerhalb des Codes) zu protokollieren, unter der ich eine Nachricht an die Protokollausgabe sende. Da diese Anwendung aus vielen Dateien besteht, möchte ich eine einzelne Protokolldatei erstellen, damit ich den Kontrollfluss der Anwendung besser verstehen kann.
Folgendes weiß ich:
Zum Abrufen des Funktionsnamens kann
function_name.__name__
ich den Funktionsnamen verwenden , möchte ihn jedoch nicht verwenden (damit ich schnell ein Generikum kopieren undLog.info("Message")
in den Hauptteil aller Funktionen einfügen kann). Ich weiß, dass dies in C mit einem__func__
Makro möglich ist, bin mir aber bei Python nicht sicher.Um den Dateinamen und die Zeilennummer zu erhalten, habe ich gesehen, dass (und ich glaube das) meine Anwendung die Python-
locals()
Funktion verwendet, aber in einer Syntax, die mir nicht vollständig bekannt ist, zB:options = "LOG.debug('%(flag)s : %(flag_get)s' % locals())
und ich habe es mit like versucht,LOG.info("My message %s" % locals())
was so etwas erzeugt{'self': <__main__.Class_name object at 0x22f8cd0>}
. Irgendwelche Eingaben dazu bitte?Ich weiß, wie man die Protokollierung verwendet und einen Handler hinzufügt, um in einer Datei zu protokollieren, bin mir jedoch nicht sicher, ob eine einzelne Datei zum Aufzeichnen aller Protokollnachrichten in der richtigen Reihenfolge der Funktionsaufrufe im Projekt verwendet werden kann.
Ich würde mich über jede Hilfe sehr freuen.
Vielen Dank!
import pdb; pdb.set_trace()
und dann den Code interaktiv durchlaufen. Dies kann Ihnen helfen, den Programmfluss zu verfolgen.Antworten:
Sie haben hier einige geringfügig verwandte Fragen.
Ich beginne mit dem einfachsten: (3). Mit können
logging
Sie alle Aufrufe zu einer einzelnen Protokolldatei oder einem anderen Ausgabeziel zusammenfassen: Sie befinden sich in der Reihenfolge, in der sie im Prozess aufgetreten sind.Als nächstes: (2).
locals()
liefert ein Diktat des aktuellen Umfangs. In einer Methode ohne andere Argumente haben Sie also einenself
Gültigkeitsbereich, der einen Verweis auf die aktuelle Instanz enthält. Der Trick, der Sie verblüfft, ist die Zeichenfolgenformatierung mit einem Diktat als RHS des%
Operators."%(foo)s" % bar
wird durch den Wert von ersetztbar["foo"]
.Schließlich können Sie einige Introspektionstricks verwenden, die denen ähneln, mit denen Sie
pdb
weitere Informationen protokollieren können:Dadurch werden die übergebene Nachricht sowie der (ursprüngliche) Funktionsname, der Dateiname, in dem die Definition angezeigt wird, und die Zeile in dieser Datei protokolliert. Schauen Sie sich inspect an - Inspizieren Sie lebende Objekte auf weitere Details.
Wie bereits in meinem Kommentar erwähnt, können Sie jederzeit in eine
pdb
interaktive Debugging-Eingabeaufforderung wechseln, indem Sie die Zeile einfügenimport pdb; pdb.set_trace()
und Ihr Programm erneut ausführen. Auf diese Weise können Sie den Code schrittweise durchlaufen und die Daten nach Belieben überprüfen.quelle
'%(foo)s : %(bar)s'
auch denbar["foo"]
Wert des ' drucken ? Oder ist es etwas anders als Ihr Beispiel?%(<foo>)s
durch den Wert des Objekts ersetzt, auf das im Diktat von verwiesen wird<foo>
. Weitere Beispiele / Details finden Sie unter docs.python.org/library/stdtypes.html#string-formattingDie richtige Antwort hierfür ist die Verwendung der bereits bereitgestellten
funcName
VariablenDann, wo immer Sie wollen, fügen Sie einfach hinzu:
Beispielausgabe eines Skripts, an dem ich gerade arbeite:
quelle
getLogger(__name__)
logging.getLogger('root')
wahrscheinlich nicht dasroot
, was Sie erwarten, es ist nicht der Logger, sondern ein gewöhnlicher Logger mit dem Namen 'root'.funcname
,linename
Undlineno
Informationen über die letzte Funktion zur Verfügung stellen, die die Protokollierung taten.Wenn Sie einen Wrapper für Logger haben (z. B. Singleton-Logger), funktioniert die Antwort von @ synthetizerpatel möglicherweise nicht für Sie.
Um die anderen Anrufer im Aufrufstapel herauszufinden, haben Sie folgende Möglichkeiten:
quelle
logging
Skipping - Klasse unterstützt Stapelebene out-of-the-box: Methoden wielog()
,debug()
etc. nun ein akzeptierenstacklevel
Argument. Siehe die Dokumente .