Gestire i file di log in Python: scrittura, rotazione e lettura

by theArchitect
SHARE
Gestire i file di log in Python: scrittura, rotazione e lettura
© Guida-HTML5.it

Introduzione

Quando si parla di gestione dei file in Python, uno degli usi più pratici e professionali è la gestione dei file di log. I log servono a registrare eventi, errori, attività utente, operazioni di sistema e informazioni utili al debug. In un progetto reale, non basta scrivere qualche riga su un file: bisogna anche organizzare i messaggi, separare i livelli di gravità, evitare file troppo grandi e, spesso, leggere o analizzare i log generati.

Questo tutorial ti mostra un approccio pratico e professionale alla gestione dei file di log in Python usando il modulo standard logging. Vedremo come scrivere log su file, come formattarli in modo leggibile, come ruotarli automaticamente e come leggere un file di log per estrarre informazioni utili.

Il vantaggio di usare logging rispetto a semplici print() è enorme: puoi controllare il livello di dettaglio, inviare i messaggi sia su console sia su file e mantenere il codice più pulito e scalabile.

Codice completo

import logging
from logging.handlers import RotatingFileHandler
from pathlib import Path
from datetime import datetime

# Percorso della cartella dei log
LOG_DIR = Path("logs")
LOG_DIR.mkdir(exist_ok=True)

# File di log principale
LOG_FILE = LOG_DIR / "app.log"

# Creazione del logger
logger = logging.getLogger("mia_app")
logger.setLevel(logging.DEBUG)

# Evita di aggiungere handler duplicati se lo script viene rieseguito
if not logger.handlers:
    # Formato dei messaggi di log
    formatter = logging.Formatter(
        fmt="%(asctime)s | %(levelname)s | %(name)s | %(message)s",
        datefmt="%Y-%m-%d %H:%M:%S"
    )

    # Handler con rotazione: massimo 1 MB, fino a 3 backup
    file_handler = RotatingFileHandler(
        LOG_FILE,
        maxBytes=1_000_000,
        backupCount=3,
        encoding="utf-8"
    )
    file_handler.setLevel(logging.DEBUG)
    file_handler.setFormatter(formatter)

    # Handler anche su console
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.INFO)
    console_handler.setFormatter(formatter)

    logger.addHandler(file_handler)
    logger.addHandler(console_handler)


def calcola_sconto(prezzo: float, percentuale: float) -

Spiegazione

Il codice si basa sul modulo standard logging, che è la soluzione consigliata in Python per gestire messaggi informativi, avvisi ed errori. Invece di scrivere manualmente su un file con open(..., "a"), il logger si occupa di tutto in modo strutturato.

1. Creazione della cartella dei log

Con Path("logs").mkdir(exist_ok=True) creiamo la cartella logs se non esiste già. Usare pathlib rende il codice più leggibile e portabile rispetto alla gestione manuale delle stringhe di percorso.

2. Configurazione del logger

Il logger viene creato con logging.getLogger("mia_app"). Il nome aiuta a identificare l’origine dei messaggi, soprattutto in progetti grandi. Il livello DEBUG permette di registrare tutti i messaggi, ma poi ogni handler può filtrare in modo diverso.

3. Formato dei messaggi

Il formatter definisce come appariranno i log nel file e in console. Nel nostro esempio ogni riga contiene:

  • data e ora
  • livello del messaggio
  • nome del logger
  • testo del messaggio

Questo formato è molto utile quando devi analizzare problemi in produzione o confrontare eventi avvenuti in momenti diversi.

4. Rotazione automatica dei file

Il RotatingFileHandler è fondamentale nella gestione dei file di log. Senza rotazione, un file di log può crescere senza controllo. Con questa configurazione, quando il file supera 1 MB, Python crea automaticamente una copia di backup e continua a scrivere su un nuovo file.

Il parametro backupCount=3 indica che verranno mantenute al massimo 3 copie precedenti, ad esempio:

  • app.log
  • app.log.1
  • app.log.2
  • app.log.3

5. Livelli di log

Nel codice usiamo livelli diversi:

  • DEBUG: informazioni molto dettagliate, utili in fase di sviluppo
  • INFO: eventi normali e significativi, come il completamento di un calcolo
  • WARNING: situazioni sospette o fuori range, ma non bloccanti
  • ERROR: errore reale che impedisce l’operazione

6. Funzione di esempio

La funzione calcola_sconto() mostra un caso reale: validazione dei dati, registrazione dei passaggi e gestione delle eccezioni. Se il prezzo è negativo, viene generato un errore e il logger registra il problema.

7. Lettura del file di log

La funzione leggi_log() apre il file in modalità lettura e cerca una parola chiave in ogni riga. Questo è utile per fare una semplice analisi dei log, ad esempio per trovare tutte le occorrenze di un certo evento o di un errore specifico.

Noterai che qui usiamo ancora with open(...): è corretto perché la lettura di un file resta un’operazione di gestione file classica, ma il contenuto del file è stato prodotto in modo professionale dal sistema di logging.

Best practice

  • Non usare print per i log applicativi: print() va bene per test veloci, ma non offre livelli, filtri, formattazione e gestione centralizzata.
  • Usa sempre livelli appropriati: non registrare tutto come INFO. Scegli DEBUG, INFO, WARNING o ERROR in base al contesto.
  • Configura la rotazione dei file: è una protezione essenziale contro file di log troppo grandi.
  • Usa l’encoding UTF-8: evita problemi con caratteri accentati o simboli speciali nei messaggi.
  • Evita handler duplicati: se il modulo viene importato più volte, controlla che il logger non aggiunga più handler uguali.
  • Registra eccezioni con logger.exception(): questo metodo aggiunge automaticamente anche lo stack trace, rendendo il debug molto più semplice.
  • Non salvare dati sensibili: nei log non inserire password, token, numeri di carta o informazioni personali non necessarie.

Riepilogo

La gestione dei file di log in Python è una competenza molto utile per sviluppare applicazioni affidabili e manutenibili. Con il modulo logging puoi scrivere messaggi strutturati su file, visualizzarli anche in console, distinguere i livelli di gravità e impedire che i file crescano all’infinito grazie alla rotazione automatica.

Inoltre, leggere e filtrare i log ti aiuta a diagnosticare problemi, monitorare il comportamento dell’applicazione e costruire piccoli strumenti di analisi. In sintesi:

  • usa logging al posto di print();
  • salva i log in una cartella dedicata;
  • formatta bene i messaggi;
  • attiva la rotazione;
  • proteggi i dati sensibili.

Approfondisci con risorse ufficiali

  • Python Logging HOWTO: guida ufficiale al modulo logging
  • logging — Logging facility for Python: documentazione completa del modulo
  • logging.handlers: handler avanzati, inclusi quelli per rotazione e rete
  • pathlib: gestione moderna dei percorsi file in Python
  • datetime: utile per data e ora nei messaggi di log

SHARE