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?

digy
quelle

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')
Seb
quelle
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
Codeforester
quelle
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.

Orangepips
quelle
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 .

Zeichen
quelle
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.

Hosana Gomes
quelle