Gestione degli errori Python: prova / tranne / altrimenti / finalmente nel 2026
La gestione degli errori separa il "codice che funziona sulla tua macchina" dal "codice che sopravvive alla produzione". Il comando "try / tranne" di Python sembra semplice, ma la forma completa composta da quattro parole chiave — "prova / tranne / altrimenti / finalmente" - codifica una quantità sorprendente di struttura che la maggior parte dei tutorial ignora.
Questa guida tratta: cosa significa effettivamente ciascuna parola chiave, i sei modelli che vedrai in ogni codebase di backend, quando definire le tue eccezioni e i tre anti-modelli che consentono ai bug di superare i tuoi test.
Le quattro parole chiave, appunto
La clausola "else" è sottoutilizzata. Dice "questa parte successiva dipende dal successo del tentativo, ma non voglio che sia protetto dallo stesso tranne". È il posto giusto per la felice continuazione del percorso: inserendolo all'interno di "try" vengono rilevate accidentalmente eccezioni non correlate da "ship(result)".
I sei modelli
1. Riprovare in caso di errore temporaneo
Regola: riprovare SOLO in caso di errori temporanei (rete, timeout, 429, 503). Non riprovare mai su ValueError, KeyError, TypeError: questi sono bug del codice e riprovare esegue semplicemente il bug tre volte.
2. Proteggi con else
"else" garantisce che il "file" sia stato aperto correttamente E la pulizia dell'ambito con "with". Nota: process() potrebbe sollevare ValueError — che si propagherà, NON verrà catturato da eccetto FileNotFoundError.
3. Ripulitura con finally (prima che with esistesse)
Nel codice moderno utilizzeresti with db.connect() come conn: — with è lo zucchero su "try /finalmente" per il comune caso di pulizia. Raggiungere "finalmente" esplicito solo quando la risorsa non supporta il protocollo di gestione del contesto.
4. Rilanciare nuovamente aggiungendo contesto
raise NewException(...) from e concatena l'eccezione originale a quella nuova in modo che il traceback mostri ENTRAMBI. Non scrivere mai raise NewException(str(e)) — che scarta il traceback originale.
5. Cattura l'eccezione più stretta possibile
Regola: più stretta è l'eccezione, meglio è. Se non sai cosa può generare il `processo', eseguilo e scoprilo. "eccetto Eccezione:" è un odore di codice nel 90% dei casi.
6. raise inside Exception — rilancia in modo pulito
Il semplice raise mantiene intatta la traccia originale. Non usare mai "raise e" (Python 3 è intelligente a riguardo, ma il semplice "raise" è la forma idiomatica).
Eccezioni personalizzate: quando ne vale la pena
Definisci la tua classe di eccezione quando:
1. I chiamanti devono specificare "eccetto MyError:" (ovvero, hai un'API richiamabile e gli utenti devono effettuare la ramificazione in base al tipo di errore).
2. La tua libreria/servizio solleva molteplici errori correlati che condividono il contesto.
Ora i chiamanti possono intercettare in modo ampio (eccetto PaymentError) o in modo ristretto (eccetto CardDeclinedError). Gli attributi strutturati sull'eccezione (e.card_last4) consentono ai gestori di errori di creare un'esperienza utente utile senza analizzare i messaggi di eccezione.
Anti-pattern: definizione di un'eccezione personalizzata che esiste per essere sollevata solo una volta e mai intercettata. Si tratta semplicemente di "raise ValueError("...")`. Le eccezioni personalizzate guadagnano il loro peso se vengono catturate.
Tre anti-pattern che nascondono bug
Anti-modello 1: Nudo eccetto
Il semplice except cattura i segnali che dovrebbero uscire dal programma (Ctrl-C, sys.exit, MemoryError). Non scriverlo mai. Se vuoi veramente catturare ogni eccezione non fatale, usa "eccetto Eccezione:" - che ANCORA cattura troppo, ma almeno rispetta Ctrl-C.
Anti-pattern 2: Silenziamento senza registrazione
Ogni eccezione rilevata dovrebbe essere gestita (con uno specifico fallback) o registrata. pass in un'eccezione è un bug al rallentatore: il codice sembra funzionare mentre scarta silenziosamente i dati.
Anti-modello 3: eccetto Eccezione: intorno a tutto
Problema: se stripe.charge ha avuto successo ma send_receipt ha fallito, il cliente ha ricevuto l'addebito E tu hai inghiottito l'errore. L'"eccetto" copre quattro diverse modalità di errore e non è possibile distinguerle.
Correzione: restringere l'ambito della prova + ramificare l'eccezione per il limite del modulo.
Ogni tentativo copre UN'operazione. Tutti tranne sanno cosa fare riguardo a QUESTO specifico fallimento. Questa è la gestione degli errori a livello di produzione.
Una buona gestione degli errori è più una questione di progettazione che di sintassi. provare / tranne / altrimenti / finalmente ti fornisce gli strumenti; la disciplina è scegliere il tipo giusto, l'ambito di prova più ristretto possibile e non mettere mai a tacere gli errori che non capisci.
Passaggio successivo: il percorso Foundations contiene 10 lezioni sulla gestione delle eccezioni, sulle eccezioni personalizzate e sull'istruzione "with" — con Python reale in esecuzione nel tuo browser.