Come registrare il nome del file sorgente e il numero di riga in Python


123

È possibile decorare / estendere il sistema di registrazione standard python, in modo che quando viene richiamato un metodo di registrazione, esso registra anche il file e il numero di riga in cui è stato richiamato o forse il metodo che lo ha invocato?

Risposte:


228

Certo, controlla i formattatori nella registrazione dei documenti. In particolare le variabili lineno e pathname.

% (pathname) s Percorso completo del file di origine in cui è stata eseguita la chiamata di registrazione (se disponibile).

% (nomefile) s Parte del nome file del percorso.

% (modulo) s Modulo (parte del nome del nome del file).

% (funcName) s Nome della funzione che contiene la chiamata di registrazione.

% (lineno) d Numero della riga di origine in cui è stata emessa la chiamata di registrazione (se disponibile).

Assomiglia a questo:

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

1
E, sì, è necessario considerare il pasticcio maiuscolo / minuscolo nelle variabili.
Tom Pohl

1
Altrimenti indicato come "caso di cammello implementato molto male".
Jon Spencer

81

Oltre alla risposta molto utile di Seb , ecco un pratico frammento di codice che dimostra l'utilizzo del logger con un formato ragionevole:

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

Genera questo output:

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
Usa questo per maggiori dettagli: formatter = logging.Formatter ('% (asctime) s,% (levelname) -8s [% (filename) s:% (module) s:% (funcName) s:% (lineno) d] % (message) s ')
Girish Gupta

c'è un modo per cambiare solo in un punto all'inizio del codice se i messaggi di registrazione vengono stampati o meno? Vorrei due modalità, una con molte stampe per vedere cosa fa esattamente il programma; e uno, per quando è abbastanza stabile, dove non viene mostrato alcun output.
Marie. P.

3
@ Marie.P. non fare domande diverse nei commenti. La risposta è però i livelli di registrazione.
bugmenot123

4

Per costruire su quanto sopra in un modo che invia la registrazione di debug allo standard out:

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

Mettere quanto sopra in un file chiamato debug_logging_example.pyproduce l'output:

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

Quindi, se vuoi disattivare la disconnessione, commenta root.setLevel(logging.DEBUG).

Per singoli file (ad es. Compiti di classe) ho trovato che questo è un modo molto migliore di farlo rispetto all'utilizzo di print()istruzioni. Dove ti consente di disattivare l'output di debug in un unico posto prima di inviarlo.


1

Per gli sviluppatori che utilizzano PyCharm o Eclipse pydev, quanto segue produrrà un collegamento all'origine dell'istruzione di log nell'output del log della console:

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

Vedi collegamenti ipertestuali ai file sorgente di Pydev nella console Eclipse per discussioni e cronologie più lunghe.


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)

Diversamente dalle altre risposte, questo registrerà il percorso completo del file e il nome della funzione che potrebbe essersi verificato un errore. Questo è utile se hai un progetto con più di un modulo e diversi file con lo stesso nome distribuiti in questi moduli.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.