Last chance! 50% off DataCamp Premium
Sale ends in
Se stai iniziando con Python e vuoi saperne di più, segui il corso Introduction to Data Science in Python di DataCamp.
In generale, il logging è un modo per mantenere un registro generato da un programma. Un file di log di solito contiene una serie di record degli eventi che si verificano nel tuo codice (per esempio, un codice Python) o in un sistema operativo. Questi eventi o messaggi vengono scritti in un file di log; un messaggio o evento può anche essere una comunicazione tra utenti diversi.
Di solito dipende dagli sviluppatori come preferiscono generare i log. Magari vogliono registrare ogni operazione di un'applicazione che hanno sviluppato, fare log solo quando si verifica un errore, oppure monitorare e registrare le operazioni essenziali eseguite da un utente. Un'operazione essenziale potrebbe essere verificare da quale utente finale o indirizzo IP è stata effettuata l'accesso all'applicazione o al server e, nel caso di un tentativo non riuscito, lo sviluppatore potrebbe poi consultare i log e ottenere indicazioni migliori rispetto a un semplice stack trace.
Un esempio calzante è quando provi a installare qualcosa su Linux come utente sudo senza esserlo. Vedi il messaggio "Xyz is not in the sudoers file. This incident will be reported", che viene scritto in un file di log.
La buona notizia è che Python include un modulo di logging integrato, pronto all'uso senza bisogno di installazione.
Il logging, nello spirito, è simile a una funzione Print. Tuttavia, una funzione print non include molte informazioni utili per uno sviluppatore. Il logging, invece, può registrare timestamp e numero di riga in cui si è verificato l'errore. Può inviare errori o altre informazioni a file, socket, ecc., e ti offre cinque livelli di severità in base ai quali puoi differenziare il tuo logging.
I cinque livelli di logging, come mostrato qui, sono:
Debug (10): Utile per diagnosticare problemi nel codice.
Info (20): Può fungere da conferma che non ci sono bug nel codice. Un buon caso d'uso del livello Info è il monitoraggio dell'avanzamento dell'addestramento di un modello di machine learning.
Warning (30): Indica un problema che potrebbe verificarsi in futuro. Per esempio, l'avviso che un modulo potrebbe essere deprecato in futuro o un avviso di poca RAM.
Error (40): Un bug serio nel codice; potrebbe essere un errore di sintassi, memoria esaurita, eccezioni.
Critical (50): Un errore a causa del quale il programma potrebbe smettere di funzionare o uscire bruscamente.
Basta teoria, giusto?
Vediamo ora come implementare il logging in un codice Python.
Ma prima, diamo un'occhiata alla tabella degli attributi del logging: userai alcuni degli attributi qui sotto in questo tutorial.
import logging
Ora chiamerai il metodo basicConfig(), che ti aiuta a creare una configurazione di base perché il sistema di logging funzioni senza intoppi.
Ti permette di impostare i seguenti parametri:
Ricorda che il metodo basicConfig() è facoltativo e potresti volerlo saltare.
logging.basicConfig()
Costruiamo ora i cinque livelli di severità.
logging.debug("A Debug Logging Message")
logging.info("A Info Logging Message")
logging.warning("A Warning Logging Message")
WARNING:root:A Warning Logging Message
logging.error("An Error Logging Message")
ERROR:root:An Error Logging Message
logging.critical("A Critical Logging Message")
CRITICAL:root:A Critical Logging Message
Come puoi osservare dagli output sopra, solo quelli con livello di severità maggiore di 20 sono stati registrati con successo, poiché questa è la configurazione predefinita del logging in Python.
Tuttavia, come detto sopra, puoi modificare i livelli di severità usando il metodo basicConfig(). Qui imposterai il livello di severità a 20, il che significa che verranno registrati i livelli di logging con severità maggiore di 10.
Nota: Riavvia il kernel prima di eseguire le celle qui sotto per vedere l'output corretto.
import logging
logging.basicConfig(level=logging.INFO)
logging.debug("A Debug Logging Message")
logging.info("A Info Logging Message")
INFO:root:A Info Logging Message
logging.warning("A Warning Logging Message")
WARNING:root:A Warning Logging Message
logging.error("An Error Logging Message")
ERROR:root:An Error Logging Message
logging.critical("A Critical Logging Message")
CRITICAL:root:A Critical Logging Message
Ora registriamo gli output sopra in un file di log. Per farlo, userai il metodo basicConfig().
import logging
logging.basicConfig(level = logging.INFO, filename = 'datacamp.log')
logging.debug("A Debug Logging Message")
logging.info("A Info Logging Message")
logging.warning("A Warning Logging Message")
logging.error("An Error Logging Message")
logging.critical("A Critical Logging Message")

Come puoi vedere, ora i log vengono generati in un file di log datacamp.log. Eseguendo più volte le celle sopra, noterai che i log verranno aggiunti al file di log ogni volta. Per impostazione predefinita, il file è in modalità append.

Puoi usare la parola chiave filemode per evitare che il file di log venga scritto con più copie di log, cioè in modalità append. Il filemode può essere cambiato in modalità write, che sovrascriverà i log precedenti e salverà solo quelli correnti. Poiché il filemode è impostato su w, significa che il file di log verrà aperto in write mode ogni volta che viene eseguito basicConfig(), sovrascrivendo di fatto il file.
La funzionalità di modalità file nel logging è simile alla normale gestione dei file offerta da Python.
import logging
logging.basicConfig(level = logging.INFO, filename = 'datacamp.log', filemode = 'w')
logging.debug("A Debug Logging Message")
logging.info("A Info Logging Message")
logging.warning("A Warning Logging Message")
logging.error("An Error Logging Message")
logging.critical("A Critical Logging Message")
Eseguiamo le righe di codice sopra più volte. Noterai che questa volta verranno salvate solo le voci di log correnti e quelle precedenti verranno sovrascritte, come mostrato sotto.

Vediamo altri attributi del logging come data, ora, numero di riga in cui è stato generato un warning o un errore. Ormai concorderai che tutti questi sono vantaggi rispetto a una semplice funzione print e sono molto più potenti di una mera print.
Per riuscirci, passerai gli attributi di logging asctime e lineno. Inoltre passerai l'attributo message, che sarà un segnaposto per il messaggio che vuoi mostrare nei log. Tutti questi attributi verranno passati al metodo format.
import logging
logging.basicConfig(format='Date-Time : %(asctime)s : Line No. : %(lineno)d - %(message)s', \
level = logging.DEBUG)
logging.debug("A Debug Logging Message")
logging.info("A Info Logging Message")
logging.warning("A Warning Logging Message")
logging.error("An Error Logging Message")
logging.critical("A Critical Logging Message")
Date-Time : 2020-03-18 23:58:12,429 : Line No. : 1 - A Debug Logging Message
Date-Time : 2020-03-18 23:58:12,436 : Line No. : 2 - A Info Logging Message
Date-Time : 2020-03-18 23:58:12,437 : Line No. : 3 - A Warning Logging Message
Date-Time : 2020-03-18 23:58:12,440 : Line No. : 4 - An Error Logging Message
Date-Time : 2020-03-18 23:58:12,441 : Line No. : 5 - A Critical Logging Message
Vediamo le definizioni di ciascun attributo direttamente da questa tabella.
asctime: Ora leggibile per l'utente in cui è stato generato il LogRecord. Per impostazione predefinita, ha la forma 2020-03-18 22:24:42,670 (i numeri dopo la virgola sono i millisecondi). Poiché questo attributo è una stringa, usi quindi la parola chiave s dopo di esso.
lineno: Numero di riga sorgente in cui è stata effettuata la chiamata al logging. Poiché questo attributo è un intero, usi quindi la parola chiave d dopo di esso.
message: Il messaggio registrato, calcolato come msg % args. Viene impostato quando viene invocato Formatter.format(). Se non specifichi questo attributo quando usi il parametro format(), i messaggi che vuoi registrare non verranno generati. Analogamente, per l'attributo message usi s poiché è una stringa.
funcName: Mostra il nome del modulo o della funzione in cui il log è generato. È utile quando hai molte funzioni nel tuo codice e vuoi separare i log in base alla funzione o al metodo a cui appartengono.
Facciamo un esempio semplice e vediamo come inserire la funzione di debug del logging al posto della print.
import logging
logging.basicConfig(format='%(asctime)s :: %(levelname)s :: %(funcName)s :: %(lineno)d \
:: %(message)s', level = logging.INFO)
def addition(x, y):
add = x + y
return add
def subtract(x, y):
sub = x - y
return sub
def multiply(x, y):
mul = x * y
return mul
def divide(x, y):
div = x / y
return div
def exponent(x, y):
exp = x ** y
return exp
num1 = 20
num2 = 2
def main():
add_result = addition(num1, num2)
logging.info('Add: {} + {} = {}'.format(num1, num2, add_result))
sub_result = subtract(num1, num2)
logging.info('Sub: {} - {} = {}'.format(num1, num2, sub_result))
mul_result = multiply(num1, num2)
logging.info('Mul: {} * {} = {}'.format(num1, num2, mul_result))
div_result = divide(num1, num2)
logging.info('Div: {} / {} = {}'.format(num1, num2, div_result))
exp_result = exponent(num1, num2)
logging.info('Exp: {} ** {} = {}'.format(num1, num2, exp_result))
main()
2020-03-19 00:01:27,372 :: INFO :: main :: 35 :: Add: 20 + 2 = 22
2020-03-19 00:01:27,376 :: INFO :: main :: 38 :: Sub: 20 - 2 = 18
2020-03-19 00:01:27,377 :: INFO :: main :: 41 :: Mul: 20 * 2 = 40
2020-03-19 00:01:27,378 :: INFO :: main :: 44 :: Div: 20 / 2 = 10.0
2020-03-19 00:01:27,379 :: INFO :: main :: 47 :: Exp: 20 ** 2 = 400
Complimenti per aver completato il tutorial.
Potresti voler provare altri attributi del logging e capire come sfruttarli nel tuo codice.
Per qualsiasi domanda relativa a questo tutorial, sentiti libero di scrivere nei commenti qui sotto.
Se stai iniziando con Python e vuoi saperne di più, segui il corso Introduction to Data Science in Python di DataCamp.
Corsi Python
Corso
Corso
Corso
blog
Tim Lu
12 min

blog
Abid Ali Awan
10 min

blog
Abid Ali Awan
15 min