🚀 Nuova versione beta disponibile! Feedback o problemi? Contattaci

Logging in Python

Codegrind TeamSep 11 2024

Il logging in Python è una pratica essenziale per monitorare il comportamento del tuo codice e diagnosticare problemi durante l’esecuzione. Python offre un modulo integrato chiamato logging, che permette di registrare messaggi di debug, informazioni, avvertimenti, errori e messaggi critici in modo flessibile. In questo articolo vedremo come utilizzare il modulo logging per tenere traccia delle attività del programma, evitando di usare le semplici stampe con print().

Vantaggi del Logging

Usare logging offre diversi vantaggi rispetto a print():

  • Livelli di gravità: Il modulo logging consente di classificare i messaggi in base alla loro importanza (debug, info, warning, error, critical).
  • Flessibilità: Puoi inviare messaggi di log a file, console o anche a sistemi di log esterni.
  • Formato personalizzato: Puoi personalizzare il formato dei messaggi di log per includere informazioni come data, ora, nome del modulo e altro.
  • Configurabilità: Puoi facilmente attivare o disattivare il logging a vari livelli di gravità senza modificare il codice.

Livelli di Logging

Il modulo logging ha cinque livelli di gravità predefiniti:

  1. DEBUG: Dettagli diagnostici utili durante lo sviluppo.
  2. INFO: Messaggi informativi sull’esecuzione del programma.
  3. WARNING: Indicazioni di problemi potenziali, ma non critici.
  4. ERROR: Errori che impediscono il corretto funzionamento di una parte del programma.
  5. CRITICAL: Errori gravi che potrebbero causare la chiusura del programma.

Esempio di Logging con Vari Livelli

import logging

# Configura il logging di base
logging.basicConfig(level=logging.DEBUG)

logging.debug("Questo è un messaggio di debug.")
logging.info("Questo è un messaggio informativo.")
logging.warning("Questo è un avvertimento.")
logging.error("Questo è un messaggio di errore.")
logging.critical("Questo è un messaggio critico.")

Output:

DEBUG:root:Questo è un messaggio di debug.
INFO:root:Questo è un messaggio informativo.
WARNING:root:Questo è un avvertimento.
ERROR:root:Questo è un messaggio di errore.
CRITICAL:root:Questo è un messaggio critico.

In questo esempio, utilizziamo logging.basicConfig() per configurare il livello minimo di logging e poi loggiamo messaggi di vari livelli di gravità. I messaggi al di sotto del livello impostato non verranno mostrati.

Configurazione di Base del Logging

Il modulo logging può essere configurato in modo semplice o avanzato, a seconda delle esigenze. Vediamo un esempio di configurazione di base:

Esempio di Configurazione di Base

import logging

logging.basicConfig(
    level=logging.INFO,             # Livello minimo di log
    format="%(asctime)s - %(levelname)s - %(message)s"  # Formato del messaggio
)

logging.info("Programma iniziato")

Output:

2024-09-11 10:30:15,123 - INFO - Programma iniziato

In questo esempio:

  • level=logging.INFO: Imposta il livello di logging su INFO. I messaggi di debug non saranno mostrati.
  • format="...": Definisce il formato dei messaggi di log. Qui abbiamo incluso l’ora, il livello di gravità e il messaggio.

Modificare il Livello di Logging

Puoi modificare facilmente il livello minimo di logging a seconda delle esigenze. Ad esempio, durante lo sviluppo puoi voler vedere i messaggi di debug:

logging.basicConfig(level=logging.DEBUG)

Oppure, in produzione puoi limitare i log a solo messaggi di warning o errori:

logging.basicConfig(level=logging.WARNING)

Logging su File

Oltre a inviare i messaggi di log alla console, è comune volerli scrivere su un file per analisi successive. Ecco come farlo:

Esempio di Logging su File

import logging

logging.basicConfig(
    filename="app.log",         # Scrive i log su un file
    level=logging.INFO,         # Livello minimo di log
    format="%(asctime)s - %(levelname)s - %(message)s"
)

logging.info("Questo messaggio verrà scritto su un file.")

In questo esempio:

  • Il parametro filename specifica il file in cui scrivere i log (app.log).
  • I messaggi di log verranno scritti su questo file anziché sulla console.

Aggiungere Log al File (Modalità Append)

Se vuoi aggiungere nuovi messaggi di log a un file esistente senza sovrascriverlo, puoi impostare la modalità filemode a 'a' (append):

logging.basicConfig(filename="app.log", filemode="a", level=logging.INFO)

Formati di Log Personalizzati

È possibile personalizzare i messaggi di log utilizzando le variabili di formattazione predefinite. Ecco alcune variabili utili:

  • %(asctime)s: Data e ora del log.
  • %(levelname)s: Livello di gravità del messaggio.
  • %(message)s: Il messaggio di log.
  • %(name)s: Nome del logger.
  • %(filename)s: Nome del file in cui si trova il codice che genera il log.

Esempio di Formattazione Avanzata

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)

logging.info("Log personalizzato con più dettagli.")

Output:

2024-09-11 10:35:23,456 - root - INFO - Log personalizzato con più dettagli.

In questo esempio, il nome del logger (root) viene incluso nel messaggio di log insieme all’ora, al livello e al messaggio.

Logger Personalizzati

Il modulo logging ti permette di creare logger personalizzati, ognuno con le proprie configurazioni. Questo è utile quando vuoi gestire log specifici per moduli o parti del programma.

Esempio di Logger Personalizzato

import logging

# Crea un logger personalizzato
logger = logging.getLogger("modulo_personalizzato")
logger.setLevel(logging.DEBUG)

# Configura il formato per questo logger
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# Crea un handler per scrivere su file
file_handler = logging.FileHandler("modulo.log")
file_handler.setFormatter(formatter)

# Aggiungi l'handler al logger
logger.addHandler(file_handler)

logger.info("Messaggio dal logger personalizzato")
logger.debug("Debug dal logger personalizzato")

In questo esempio:

  • Creiamo un logger personalizzato con getLogger("modulo_personalizzato").
  • Configuriamo un handler per scrivere su un file (modulo.log).
  • Aggiungiamo un formatter per personalizzare il formato dei log.

Gestione di Eccezioni con il Logging

Il modulo logging ti permette di registrare facilmente eccezioni e tracce degli errori (tracebacks) nei log. Puoi farlo passando l’opzione exc_info=True all’interno del messaggio di errore.

Esempio di Logging delle Eccezioni

try:
    1 / 0  # Causa un'eccezione
except ZeroDivisionError:
    logging.error("Divisione per zero", exc_info=True)

Output:

ERROR:root:Divisione per zero
Traceback (most recent call last):
  File "main.py", line 2, in <module>
    1 / 0
ZeroDivisionError: division by zero

In questo esempio, la traccia completa dell’errore viene inclusa nel log, rendendo più facile la diagnostica.

Disabilitare il Logging di Librerie Esterne

A volte, potresti voler disabilitare o abbassare il livello di logging di librerie esterne che generano troppi log. Puoi farlo modificando il livello di logging del logger della libreria.

Esempio di Disabilitazione del Logging di una Libreria

logging.getLogger("libreria_esterna").setLevel(logging.WARNING)

In questo esempio, riduciamo i messaggi di log di libreria_esterna al livello WARNING o superiore, ignorando i messaggi di debug e informativi.

Conclusione

Il logging è un potente strumento per monitorare, analizzare e risolvere problemi nel tuo codice. A differenza di print(), il logging offre livelli di gravità, formati personalizzati e la

possibilità di inviare i log a file o altre destinazioni. Con una corretta implementazione del logging, puoi migliorare la tracciabilità e la manutenibilità del tuo programma, soprattutto in ambienti complessi o in produzione.