So protokollieren Sie den Namen und die Zeilennummer der Quelldatei in Python


123

Ist es möglich, das Python-Standardprotokollierungssystem so zu dekorieren / zu erweitern, dass beim Aufrufen einer Protokollierungsmethode auch die Datei und die Zeilennummer protokolliert werden, in der sie aufgerufen wurde, oder möglicherweise die Methode, die sie aufgerufen hat?

Antworten:


227

Überprüfen Sie die Formatierer in den Protokollierungsdokumenten. Insbesondere die Variablen lineno und pathname.

% (Pfadname) s Vollständiger Pfadname der Quelldatei, in der der Protokollierungsaufruf ausgegeben wurde (falls verfügbar).

% (Dateiname) s Dateinamenanteil des Pfadnamens.

% (Modul) s Modul (Name Teil des Dateinamens).

% (funcName) s Name der Funktion, die den Protokollierungsaufruf enthält.

% (lineno) d Quellzeilennummer, unter der der Protokollierungsanruf ausgegeben wurde (falls verfügbar).

Sieht ungefähr so ​​aus:

formatter = logging.Formatter('[%(asctime)s] p%(process)s {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s','%m-%d %H:%M:%S')

1
Und ja, das Durcheinander von Groß- und Kleinbuchstaben in den Variablen muss berücksichtigt werden.
Tom Pohl

1
Andernfalls als "sehr schlecht implementierter Kamelfall" bezeichnet.
Jon Spencer

80

Hinzu kommen sehr nützliche Antwort des Seb , hier ist ein handlicher Codeausschnitt, die Logger Verwendung mit einem vernünftigen Format zeigt:

#!/usr/bin/env python
import logging

logging.basicConfig(format='%(asctime)s,%(msecs)d %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s',
    datefmt='%Y-%m-%d:%H:%M:%S',
    level=logging.DEBUG)

logger = logging.getLogger(__name__)
logger.debug("This is a debug log")
logger.info("This is an info log")
logger.critical("This is critical")
logger.error("An error occurred")

Erzeugt diese Ausgabe:

2017-06-06:17:07:02,158 DEBUG    [log.py:11] This is a debug log
2017-06-06:17:07:02,158 INFO     [log.py:12] This is an info log
2017-06-06:17:07:02,158 CRITICAL [log.py:13] This is critical
2017-06-06:17:07:02,158 ERROR    [log.py:14] An error occurred

5
Verwenden Sie dies für weitere Details: formatter = logging.Formatter ('% (asctime) s,% (levelname) -8s [% (Dateiname) s:% (Modul) s:% (funcName) s:% (lineno) d] % (Nachricht) s ')
Girish Gupta

Gibt es eine Möglichkeit, nur an einer Stelle oben im Code zu ändern, ob die Protokollierungsnachrichten gedruckt werden oder nicht? Ich möchte zwei Modi, einen mit vielen Ausdrucken, um zu sehen, was genau das Programm tut. und eine, wenn es stabil genug ist und keine Ausgabe angezeigt wird.
Marie. P.

3
@ Marie.P. Stellen Sie in Kommentaren keine anderen Fragen. Die Antwort ist jedoch die Protokollierung von Ebenen.
bugmenot123

4

So bauen Sie auf das oben Genannte auf, dass die Debug-Protokollierung an den Standardausgang gesendet wird:

import logging
import sys

root = logging.getLogger()
root.setLevel(logging.DEBUG)

ch = logging.StreamHandler(sys.stdout)
ch.setLevel(logging.DEBUG)
FORMAT = "[%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s"
formatter = logging.Formatter(FORMAT)
ch.setFormatter(formatter)
root.addHandler(ch)

logging.debug("I am sent to standard out.")

Wenn Sie das Obige in eine Datei namens debug_logging_example.pyaufrufen, wird die folgende Ausgabe erstellt:

[debug_logging_example.py:14 -             <module>() ] I am sent to standard out.

Wenn Sie dann das Abmelden deaktivieren möchten, kommentieren Sie root.setLevel(logging.DEBUG).

Für einzelne Dateien (z. B. Klassenzuweisungen) habe ich festgestellt, dass dies eine weitaus bessere Möglichkeit ist, als print()Anweisungen zu verwenden. Hier können Sie die Debug-Ausgabe an einem einzigen Ort deaktivieren, bevor Sie sie senden.


1

Für Entwickler, die PyCharm oder Eclipse pydev verwenden, wird im Folgenden ein Link zur Quelle der Protokollanweisung in der Konsolenprotokollausgabe erstellt:

import logging, sys, os
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG, format='%(message)s | \'%(name)s:%(lineno)s\'')
log = logging.getLogger(os.path.basename(__file__))


log.debug("hello logging linked to source")

Weitere Informationen und den Verlauf finden Sie unter Hyperlinks zur Pydev-Quelldatei in der Eclipse-Konsole .


0
# your imports above ...


logging.basicConfig(
    format='%(asctime)s,%(msecs)d %(levelname)-8s [%(pathname)s:%(lineno)d in 
    function %(funcName)s] %(message)s',
    datefmt='%Y-%m-%d:%H:%M:%S',
    level=logging.DEBUG
)

logger = logging.getLogger(__name__)

# your classes and methods below ...
# An naive Sample of usage:
try:
    logger.info('Sample of info log')
    # your code here
except Exception as e:
    logger.error(e)

Anders als bei den anderen Antworten werden hiermit der vollständige Dateipfad und der Funktionsname protokolliert, bei dem möglicherweise ein Fehler aufgetreten ist. Dies ist nützlich, wenn Sie ein Projekt mit mehr als einem Modul und mehreren Dateien mit demselben Namen in diesen Modulen verteilt haben.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.