Jak zarejestrować nazwę pliku źródłowego i numer linii w Pythonie


123

Czy jest możliwe udekorowanie / rozszerzenie standardowego systemu logowania w Pythonie, tak aby przy wywoływaniu metody rejestrowania rejestrował również plik i numer wiersza, w którym został wywołany, a może metodę, która go wywołała?

Odpowiedzi:


228

Jasne, sprawdź elementy formatujące w dokumentach rejestrowania. W szczególności zmienne lineno i pathname.

% (pathname) s Pełna nazwa ścieżki do pliku źródłowego, w którym zostało wysłane wywołanie logowania (jeśli jest dostępne).

% (filename) s Część nazwy pliku w nazwie ścieżki.

% (module) s Moduł (część nazwy pliku).

% (funcName) s Nazwa funkcji zawierającej wywołanie logowania.

% (lineno) d Numer linii źródłowej, w której zostało wysłane wywołanie logowania (jeśli jest dostępne).

Wygląda mniej więcej tak:

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

1
I tak, należy wziąć pod uwagę bałagan dużych / małych liter w zmiennych.
Tom Pohl

1
Inaczej określany jako „bardzo źle zrealizowany przypadek wielbłąda”.
Jon Spencer

81

Oprócz bardzo przydatnej odpowiedzi Seba , oto przydatny fragment kodu, który demonstruje użycie rejestratora w rozsądnym formacie:

#!/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")

Generuje ten wynik:

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
Użyj tego, aby uzyskać więcej informacji: formatter = logging.Formatter ('% (asctime) s,% (levelname) -8s [% (filename) s:% (module) s:% (funcName) s:% (lineno) d] % (wiadomość) s ')
Girish Gupta

czy istnieje sposób, aby zmienić tylko w jednym miejscu na górze kodu, niezależnie od tego, czy komunikaty logowania są drukowane, czy nie? Chciałbym mieć dwa tryby, jeden z dużą ilością wydruków, aby zobaczyć, co dokładnie robi program; i jeden, kiedy jest wystarczająco stabilny, gdzie nie jest pokazywany wynik.
Marie. P.

3
@ Marie.P. nie zadawaj różnych pytań w komentarzach. Odpowiedzią jest jednak rejestrowanie poziomów.
bugmenot123

4

Aby zbudować na powyższym w sposób, który wysyła logowanie debugowania do standardowego wyjścia:

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.")

Umieszczenie powyższego w pliku o nazwie debug_logging_example.pydaje wynik:

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

Następnie, jeśli chcesz wyłączyć wylogowywanie, komentuj root.setLevel(logging.DEBUG).

W przypadku pojedynczych plików (np. Zadań klasowych) stwierdziłem, że jest to o wiele lepszy sposób robienia tego w przeciwieństwie do używania print()instrukcji. Gdzie pozwala wyłączyć wyjście debugowania w jednym miejscu przed wysłaniem.


1

W przypadku programistów korzystających z PyCharm lub Eclipse pydev poniższe łącze do źródła instrukcji log w danych wyjściowych dziennika konsoli:

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")

Zobacz hiperłącza do plików źródłowych Pydev w konsoli Eclipse, aby uzyskać dłuższą dyskusję i historię.


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)

Inaczej niż w przypadku innych odpowiedzi, spowoduje to zarejestrowanie pełnej ścieżki pliku i nazwy funkcji, w przypadku której mógł wystąpić błąd. Jest to przydatne, jeśli masz projekt z więcej niż jednym modułem i kilkoma plikami o tej samej nazwie rozpowszechnianymi w tych modułach.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.