W3docs

Python Try...Except

Impara i blocchi try, except, else e finally di Python con esempi chiari. Gestisci ZeroDivisionError, ValueError, FileNotFoundError e altro.

Quando Python incontra un errore in fase di esecuzione, solleva un'eccezione — un oggetto che rappresenta cosa è andato storto. Senza alcuna gestione, un'eccezione termina immediatamente il programma. L'istruzione try...except consente di intercettare queste eccezioni, gestirle in modo elegante e mantenere il programma in esecuzione.

Questo capitolo tratta:

  • Il blocco try / except — intercettare un'eccezione specifica
  • Acquisire i dettagli dell'eccezione con as
  • Più clausole except e l'intercettazione di più eccezioni contemporaneamente
  • Il blocco else — codice che viene eseguito solo quando non si verifica alcuna eccezione
  • Il blocco finally — codice di pulizia che viene sempre eseguito
  • Eccezioni predefinite comuni e quando si verificano
  • Ri-sollevare eccezioni
  • Buone pratiche ed errori comuni

Il blocco try...except di base

Racchiudi il codice che potrebbe fallire in un blocco try. Se Python solleva un'eccezione, l'esecuzione salta al blocco except corrispondente invece di andare in crash.

python— editable, runs on the server

Output:

Error: division by zero

Python tenta la divisione, solleva ZeroDivisionError e il blocco except la gestisce. La clausola as e associa l'oggetto eccezione a e in modo da poter ispezionare o registrare il messaggio.

Se il blocco try ha successo, il blocco except viene saltato completamente.

Intercettare un tipo di eccezione specifico

Specifica sempre il tipo di eccezione che ti aspetti. Intercettare un tipo con nome rende chiara la tua intenzione ed evita di nascondere accidentalmente bug non correlati.

try:
    number = int("abc")
except ValueError as e:
    print(f"Could not convert: {e}")

Output:

Could not convert: invalid literal for int() with base 10: 'abc'

int("abc") solleva ValueError perché "abc" non è un intero valido. Specificare ValueError nella clausola except significa che qualsiasi altra eccezione imprevista si propagerà e verrà mostrata come errore invece di essere inghiottita silenziosamente.

Più clausole except

Un singolo blocco try può avere più clausole except — Python le controlla dall'alto verso il basso ed esegue la prima corrispondente.

def safe_index(items, index):
    try:
        return items[index]
    except IndexError:
        print("Index out of range.")
    except TypeError:
        print("Index must be an integer.")

safe_index([1, 2, 3], 10)   # IndexError
safe_index([1, 2, 3], "a")  # TypeError

Output:

Index out of range.
Index must be an integer.

L'ordine è importante: inserisci i tipi di eccezione più specifici prima di quelli più generali, in modo che il gestore specifico venga eseguito per primo.

Intercettare più eccezioni in una sola clausola

Quando due o più eccezioni richiedono la stessa risposta, raggruppale in una tupla:

try:
    value = int("not-a-number")
except (ValueError, TypeError) as e:
    print(f"Input error: {e}")

Output:

Input error: invalid literal for int() with base 10: 'not-a-number'

Il blocco else

Il blocco else viene eseguito solo quando il blocco try si completa senza sollevare alcuna eccezione. Usalo per il codice che deve essere eseguito in caso di successo ma che non necessita di protezione dagli errori:

try:
    result = 10 / 2
except ZeroDivisionError:
    print("Cannot divide by zero.")
else:
    print(f"Division succeeded. Result: {result}")

Output:

Division succeeded. Result: 5.0

Mantenere la logica del percorso di successo in else (anziché in fondo al blocco try) evita di intercettare accidentalmente le eccezioni che il codice del percorso di successo stesso potrebbe sollevare.

Il blocco finally

Il blocco finally viene eseguito in ogni caso — sia che il blocco try abbia successo, sia che un'eccezione venga intercettata, sia che un'eccezione si propaghi non intercettata. Usalo per la pulizia: chiudere file, rilasciare blocchi o disconnettersi da un database.

try:
    result = 10 / 0
except ZeroDivisionError:
    print("Error caught.")
finally:
    print("This always runs — cleanup goes here.")

Output:

Error caught.
This always runs — cleanup goes here.

Anche se commenti il blocco except, finally viene comunque eseguito prima che Python propaghi l'eccezione.

Struttura completa in sintesi

try:
    # code that may raise an exception
except SomeException as e:
    # handle the exception
except (AnotherError, YetAnother):
    # handle either of these
else:
    # runs only when try succeeded
finally:
    # always runs

Eccezioni predefinite comuni

EccezioneQuando si verifica
ZeroDivisionErrorDivisione o modulo per zero
ValueErrorTipo corretto, valore sbagliato (es. int("abc"))
TypeErrorOperazione applicata al tipo sbagliato
IndexErrorIndice della sequenza fuori intervallo
KeyErrorChiave del dizionario non trovata
FileNotFoundErrorFile o directory non esiste
AttributeErrorL'oggetto non ha tale attributo
ImportErrorIl modulo non può essere importato
NameErrorIl nome della variabile non è definito

Tutte queste ereditano dalla classe base Exception. Puoi intercettare Exception per gestirle tutte in una sola clausola, ma preferisci tipi specifici ove possibile.

Gestire un file mancante

try:
    with open("data.txt", "r") as file:
        content = file.read()
except FileNotFoundError:
    print("Error: File not found.")

Output (quando data.txt non esiste):

Error: File not found.

Ri-sollevare un'eccezione

A volte vuoi registrare un'eccezione o eseguire una pulizia parziale, ma lasciare comunque che si propaghi al chiamante. Usa un raise semplice all'interno di un blocco except:

def process():
    try:
        result = 10 / 0
    except ZeroDivisionError:
        print("Logging error...")
        raise  # re-raises the original ZeroDivisionError

try:
    process()
except ZeroDivisionError as e:
    print(f"Outer handler caught: {e}")

Output:

Logging error...
Outer handler caught: division by zero

Il raise semplice preserva il traceback originale, in modo che il debug non sia più difficile rispetto a senza il gestore.

Intercettare la classe base Exception

Puoi usare Exception come catch-all per qualsiasi errore che non termina il sistema:

try:
    result = 10 / 0
except Exception as e:
    print(f"An error occurred: {type(e).__name__}: {e}")

Output:

An error occurred: ZeroDivisionError: division by zero

type(e).__name__ fornisce il nome specifico della classe anche quando si intercetta tramite la classe base. Questo è utile nei gestori di livello superiore dove si desidera registrare ogni errore imprevisto.

Bare except — e perché evitarlo

Un bare except (senza tipo di eccezione) intercetta letteralmente tutto, inclusi KeyboardInterrupt (Ctrl+C) e SystemExit, rendendo difficile interrompere il programma:

# Avoid this pattern
try:
    result = 10 / 0
except:
    print("Some error occurred")

Preferisci except Exception se hai bisogno di un'intercettazione ampia, perché lascia comunque che KeyboardInterrupt e SystemExit si propaghino normalmente.

Buone pratiche

  • Sii specifico. Intercetta il tipo di eccezione più ristretto che abbia senso.
  • Non silenziare le eccezioni. Come minimo registra l'errore; non lasciare mai un blocco except vuoto.
  • Usa else per il codice del percorso di successo. Questo mantiene il blocco try il più piccolo possibile.
  • Usa finally per la pulizia. Oppure, ancora meglio, usa un'istruzione with — vedi Python with Statement.
  • Evita il bare except. Usa except Exception se hai bisogno di un'intercettazione ampia.
  • Ri-solleva quando appropriato. Se non puoi gestire completamente l'errore, lascia che si propaghi con raise.

Per sollevare eccezioni deliberatamente e creare le proprie classi di eccezione, vedi Python raise and Custom Exceptions.

Esercitazione

Pratica
What is the functionality of 'Try' and 'Except' in Python?
What is the functionality of 'Try' and 'Except' in Python?
Was this page helpful?