Prendimi se puoi: una guida alla gestione delle eccezioni in Python

May 09 2023
Sblocca tutto il potenziale di Python attraverso una gestione intelligente delle eccezioni In qualità di sviluppatore di software, la gestione delle eccezioni è spesso vista come un male necessario. Tuttavia, la padronanza del sistema di gestione delle eccezioni di Python può renderti un programmatore più efficiente ed efficace.

Sblocca tutto il potenziale di Python attraverso una gestione intelligente delle eccezioni

Foto di Cookie the Pom su Unsplash

Come sviluppatore di software, gestire le eccezioni è spesso visto come un male necessario. Tuttavia, la padronanza del sistema di gestione delle eccezioni di Python può renderti un programmatore più efficiente ed efficace.

In questo post del blog, fornirò una spiegazione approfondita di quanto segue:

  • Cos'è la gestione delle eccezioni?
  • La differenza tra ifistruzioni e gestione delle eccezioni
  • Utilizzo elsee finallyclausole per una corretta gestione degli errori
  • Definizione delle eccezioni personalizzate
  • Best practice per la gestione delle eccezioni

la gestione delle eccezioni è un processo di scrittura del codice per rilevare e gestire errori o eccezioni che possono verificarsi durante l'esecuzione del programma. Ciò consente agli sviluppatori di scrivere codice robusto che continua a funzionare anche di fronte a eventi o errori imprevisti, invece di bloccarsi completamente.

Quando si verifica un'eccezione, Python cerca un gestore di eccezioni corrispondente. Il codice del gestore verrà eseguito e intraprenderà le azioni appropriate, ad esempio la registrazione dell'errore, la visualizzazione di un messaggio di errore o il tentativo di ripristino dall'errore. Nel complesso, la gestione delle eccezioni aiuta a rendere le applicazioni Python più affidabili, gestibili e più facili da eseguire il debug.

La differenza tra ifistruzioni e gestione delle eccezioni

Le differenze principali tra ifistruzioni e gestione delle eccezioni in Python risiedono nei rispettivi obiettivi e scenari di utilizzo.

L' ifistruzione funge da blocco di base per la programmazione strutturata. Valuta una condizione ed esegue diversi blocchi di codice in base al fatto che la condizione sia vera o falsa. Ecco un esempio:

temperature = int(input("Please enter temperature in Fahrenheit: "))
if temperature > 100:
    print("Hot weather alert! Temperature exceeded 100°F.")
elif temperature >= 70:
    print("Warm day ahead, enjoy sunny skies.")
else:
    print("Bundle up for chilly temperatures.")

Le eccezioni vengono utilizzate per segnalare problemi e indicare aree nel codice che necessitano di miglioramenti, debug o ulteriori misure di controllo degli errori. Consentono a Python di gestire con garbo situazioni errate e continuare a eseguire lo script piuttosto che terminare bruscamente.

Considera il seguente esempio di come potresti implementare la gestione delle eccezioni per gestire meglio i potenziali errori relativi alla divisione per zero:

# Define a function that tries to divide a number by zero
def divide(x, y):
    result = x / y
    return result
# Call the divide function with x=5 and y=0
result = divide(5, 0)
print(f"Result of dividing {x} by {y}: {result}")

Traceback (most recent call last):
  File "<stdin>", line 8, in <module>
ZeroDivisionError: division by zero attempted

Possiamo gestire l'eccezione di cui sopra avvolgendo la chiamata alla funzione "divide" all'interno di un try-exceptblocco in questo modo:

# Define a function that tries to divide a number by zero
def divide(x, y):
    result = x / y
    return result
# Call the divide function with x=5 and y=0
try:
    result = divide(5, 0)
    print(f"Result of dividing {x} by {y}: {result}")
except ZeroDivisionError:
    print("Cannot divide by zero.")

Cannot divide by zero.

Per ulteriori informazioni sulle eccezioni incorporate in Python, puoi fare riferimento a [2] .

Utilizzo delle clausole Else e Finalmente per una corretta gestione degli errori

Quando si lavora con le eccezioni in Python, si consiglia di includere entrambe le clausole elsee finallynei try-exceptblocchi. La elseclausola consente di specificare cosa dovrebbe accadere se non viene sollevata alcuna eccezione, mentre la finallyclausola garantisce che determinate operazioni di pulizia vengano sempre eseguite indipendentemente dal fatto che si sia verificata un'eccezione [1] [2] .

Ad esempio, considera uno scenario in cui desideri leggere i dati da un file ed eseguire alcune operazioni su tali dati. Se si verifica un'eccezione durante la lettura del file, potresti voler registrare l'errore e interrompere ulteriormente l'elaborazione, ma vuoi comunque chiudere correttamente il file.

L'uso delle clausole elseand finallyti consentirebbe di fare proprio questo: elaborare i dati normalmente se non si verifica alcuna eccezione o gestire eventuali eccezioni in modo appropriato pur chiudendo il file alla fine. Senza queste clausole, il tuo codice sarebbe vulnerabile a perdite di risorse o gestione incompleta degli errori. Pertanto, svolgono un ruolo essenziale nella creazione di programmi robusti e affidabili.

try:
    # Open the file in read mode
    file = open("file.txt", "r")
    print("Successful opened the file")
except FileNotFoundError:
    # Handle missing files
    print("File Not Found Error: No such file or directory")
    exit()
except PermissionError:
    # Handle permission issues
    print("Permission Denied Error: Access is denied")
else:
    # All good, do something with the file data
    content = file.read().decode('utf-8')
    processed_data = process_content(content)
    
# Cleanup after ourselves even if an exception occurred above
finally:
    file.close()

Altrimenti, quando non si verificano eccezioni all'interno del tryblocco, si procede con l'elaborazione del contenuto del file nel elseramo. Infine, l'operazione di pulizia assicurata dal finallyblocco chiude il file indipendentemente dal fatto che un'eccezione sia stata sollevata in precedenza o meno [1] .

Adottando un approccio strutturato come questo, il tuo codice rimane organizzato e facile da seguire tenendo conto di potenziali errori che possono derivare dall'interazione con sistemi o input esterni.

Definizione delle eccezioni personalizzate

In Python, puoi definire eccezioni personalizzate creando sottoclassi di eccezioni integrate come Exceptiono qualsiasi altra classe che eredita direttamente da Exception.

Per fare ciò, devi creare una nuova classe che erediti da una di queste eccezioni di base e aggiungere attributi specifici per le tue esigenze. Puoi quindi utilizzare la classe di eccezione appena definita in tutto il codice, proprio come faresti con qualsiasi altra classe di eccezione incorporata.

Ecco un esempio di definizione di un'eccezione personalizzata chiamata InvalidEmailAddress:

class InvalidEmailAddress(ValueError):
    def __init__(self, message):
        super().__init__(message)
        self.msgfmt = message

Puoi sollevare questa eccezione ogni volta che incontri un formato di indirizzo email non valido:

def send_email(address):
    if isinstance(address, str) == False:
        raise InvalidEmailAddress("Invalid email address")
# Send email

>>> send_email(None)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/path/to/project/main.py", line 8, in send_email
    raise InvalidEmailAddress("Invalid email address")
InvalidEmailAddress: Invalid email address

Ecco alcune best practice relative alla gestione degli errori in Python:

  1. Progettare per il fallimento : pianifica in anticipo considerando possibili guasti e progettando il tuo programma per gestirli con garbo. Ciò significa anticipare i casi limite e implementare gestori di errori appropriati.
  2. Usa messaggi di errore descrittivi : fornisci messaggi di errore dettagliati o registri che aiutano gli utenti a capire cosa è andato storto e perché. Evita messaggi di errore generici come "Si è verificato un errore" o "È successo qualcosa di brutto". Mostra invece un messaggio amichevole che suggerisce soluzioni o fornisce collegamenti alla documentazione. Assicurati di trovare un equilibrio tra fornire istruzioni dettagliate ed evitare di ingombrare l'interfaccia utente con contenuti estranei.
  3. Riduci al minimo gli effetti collaterali : riduci al minimo le conseguenze delle azioni non riuscite isolando le sezioni di codice problematiche tramite blocchi try-finally o try-with-resources. Assicurati che le attività di pulizia vengano sempre eseguite indipendentemente dall'esito positivo o negativo.
  4. Test approfondito : Test approfondito: assicurati che i tuoi gestori di eccezioni si comportino correttamente in vari scenari eseguendo test completi.
  5. Refactoring regolare : refactoring di segmenti di codice soggetti a errori per migliorarne l'affidabilità e le prestazioni. Mantieni la tua base di codice modulare e liberamente accoppiata, consentendo a parti indipendenti di evolversi in modo indipendente senza influire negativamente sugli altri.
  6. Registra eventi importanti: tieni traccia di eventi interessanti nella tua applicazione registrandoli in un file o in un output della console. Questo ti aiuta a diagnosticare rapidamente i problemi senza dover vagliare grandi quantità di registri non strutturati.

La scrittura di codice per la gestione degli errori è parte integrante dello sviluppo del software, in particolare quando si lavora con Python, poiché consente agli sviluppatori di creare applicazioni più affidabili e robuste. Seguendo gli standard e le best practice del settore, gli sviluppatori possono ridurre i tempi di debug, garantire la qualità del codice e fornire esperienze utente migliori.

Risorse

[1]https://docs.python.org/3/tutorial/errors.html

[2]https://www.geeksforgeeks.org/python-exception-handling/