Vai al contenuto principale

Eccezioni KeyError in Python e come risolverle

Scopri tecniche chiave come la gestione delle eccezioni e la prevenzione degli errori per gestire efficacemente l'eccezione KeyError in Python.
· 6 min leggi

Scopri con l'IA

Anche i programmatori più esperti commettono errori di programmazione. Per chi usa Python, questi errori rientrano in due categorie: errori o eccezioni.

Gli errori riguardano principalmente la sintassi. Devono essere corretti perché il programma possa essere eseguito. Un'eccezione, invece, si verifica quando il codice è sintatticamente corretto, ma qualcosa interrompe il programma durante l'esecuzione. 

In questo tutorial analizzeremo una delle eccezioni più comuni sia per i neofiti sia per gli sviluppatori esperti: l'eccezione KeyError. Vedremo nei dettagli il KeyError di Python, con esempi e diverse tecniche per gestire questo tipo di eccezione. Se vuoi imparare a individuare e correggere gli errori in Python, dai un'occhiata anche al nostro tutorial Gestione di eccezioni ed errori in Python. 

Che cos'è un'eccezione KeyError?

In Python, un'eccezione KeyError è una delle eccezioni integrate progettate per gestire un'ampia gamma di condizioni di errore comuni. Un'eccezione KeyError può essere intesa come una sottoclasse, insieme a IndexError, della più generale eccezione LookupError, tutte oggetti della classe Exception.

In particolare, un KeyError viene sollevato quando si tenta di accedere a una chiave che non esiste in un dizionario. Un dizionario, per riferimento, è una struttura dati che memorizza dati in coppie chiave-valore, e il valore in un dizionario si accede tramite la sua chiave — da qui il nome, KeyError. 

Cause comuni di KeyError in Python ed esempi

Vediamo un esempio con un dizionario di paesi e relative capitali:

dictionary_capitals = {'Madrid': 'Spain',
 'Lisboa': 'Portugal', 'London': 'United Kingdom'}

Per cercare informazioni nel nostro dizionario, dobbiamo specificare la chiave tra parentesi e Python restituirà il valore associato.

dictionary_capitals['Madrid']
'Spain'

Se proviamo ad accedere a una chiave che non è nel dizionario, Python ci restituirà il messaggio di errore dell'eccezione KeyError. 

dictionary_capitals['Rome']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'Rome'

Potremmo anche incontrare l'eccezione KeyError quando tentiamo di accedere a chiavi inesistenti in altri oggetti di mappatura Python che adottano la forma di un dizionario. Per esempio, l'oggetto os.environ restituisce un dizionario che memorizza le variabili d'ambiente dell'utente come chiavi con i relativi valori associati.

Nel codice seguente, proviamo ad accedere al valore associato alla chiave USERS nel dizionario os.environ. Poiché USERS non era nel dizionario os.environ, il nostro codice solleva un KeyError.

#Calling a non-existent environmental variable
os.environ['USERS']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/os.py", line 679, in __getitem__
    raise KeyError(key) from None
KeyError: 'USERS'

A quanto pare, i dizionari sono molto comuni in Python. Un altro esempio è l'implementazione di qualcosa di più astratto chiamato hashmap. Dai un'occhiata al nostro tutorial Guida alle hashmap in Python per saperne di più sulle hashmap.

Gestire le eccezioni KeyError in Python

Esploriamo i metodi per gestire le eccezioni KeyError. Abbiamo due strategie: possiamo prevenire il KeyError oppure intercettare il KeyError con la gestione delle eccezioni. 

Prevenire i KeyError

Come abbiamo visto, Python solleverà un KeyError se proviamo ad accedere a una chiave inesistente. Per evitarlo, possiamo accedere alle chiavi in un dizionario usando il metodo .get() per rendere il nostro codice più tollerante. Se, usando questo metodo, incontriamo una chiave inesistente, Python restituirà un valore None invece di un KeyError. Questa è una buona soluzione.

print(dictionary_capitals.get('Prague'))
None

In alternativa, possiamo verificare se una chiave esiste prima di accedervi. Questo modo di prevenire le eccezioni è noto come "Look Before You Leap", o in breve LBYL. In questo caso, possiamo usare istruzioni if per controllare se la chiave esiste e, se non esiste, gestire il problema nel blocco else.

capital = "Prague"
if capital in dictionary_capitals.keys():
    value = dictionary_capitals[capital]
else:
    print("The key {} is not present in the dictionary".format(capital)) 

Intercettare KeyError con la gestione delle eccezioni

Una seconda strategia è nota come "Easier to Ask Forgiveness Than Permission". EAFP, come viene chiamata, è in realtà il modo più standard di gestire le eccezioni in Python. 

Adottare lo stile EAFP significa presumere l'esistenza di chiavi valide e catturare le eccezioni se l'assunzione risulta falsa. Mentre l'approccio LBYL si basa su istruzioni if/else, l'approccio EAFP si basa su blocchi try/except. 

Nel seguente esempio, invece di verificare se la chiave è presente, proviamo ad accedere alla chiave desiderata. Se, per qualche motivo, la chiave non è presente, catturiamo il KeyError nel blocco except e lo gestiamo in modo appropriato.

capital = "Prague"
try:
     value = dictionary_capitals[capital]
except KeyError:
     print("The key {} is not present in the dictionary".format(capital)) 

Gestione avanzata dei KeyError in Python

Usare defaultdict per la gestione automatica delle chiavi

Abbiamo visto che, ogni volta che proviamo ad accedere a una chiave non presente nel nostro dizionario, Python restituirà un'eccezione KeyError. Il metodo .get() che abbiamo visto è un approccio tollerante agli errori che funziona, ma non è ottimizzato.

Il modulo Collections offre defaultdict, un approccio più ottimizzato per gestire le voci di un dizionario. A differenza dei dizionari standard, che sollevano un KeyError se proviamo ad accedere a una chiave inesistente, un defaultdict ci consente di specificare un valore predefinito che viene restituito ogni volta che una chiave non viene trovata. Il codice seguente mostra come importare defaultdict da Collections e creare un valore predefinito con una funzione lambda. Se le funzioni lambda ti confondono, consulta il nostro tutorial Python lambda per saperne di più.

from collections import defaultdict 

# Defining the dict 
capitals = defaultdict(lambda: "The key doesn't exist") 
capitals['Madrid'] = 'Spain'
capitals['Lisboa'] = 'Portugal'
print(capitals['Madrid']) 
print(capitals['Lisboa']) 
print(capitals['Ankara'])
Spain
Portugal
The key doesn't exist

Sollevare intenzionalmente KeyError

Infine, va detto che, in alcune circostanze, può essere appropriato sollevare intenzionalmente un KeyError per imporre determinati vincoli.

Sappiamo che, in molti casi, le funzioni dipendono dalla disponibilità di dati specifici per svolgere le proprie operazioni. Attivare manualmente un KeyError garantisce quindi che la funzione fallisca in modo chiaro e prevedibile quando mancano i dati necessari. In questi casi, il messaggio di errore fornito con il KeyError ci aiuta a capire esattamente cosa non andava nell'input fornito, rendendo il debug più semplice.

Chiarifichiamo con un esempio. Qui abbiamo creato una funzione che accetta un dizionario come argomento. L'utente deve fornire il dizionario con le chiavi corrette perché la funzione funzioni correttamente. Creiamo una funzione in questo caso perché vogliamo sapere subito se le chiavi mancano, invece di lasciare che gli errori persistano più avanti nel codice. 

def my_function(my_dict): 
    if 'critical_key' not in my_dict: 
        raise KeyError('critical_key is missing from the dictionary. Please modify the dictionary')

Conclusione

Speriamo che questo articolo ti sia piaciuto. KeyError è una delle eccezioni più comuni che uno sviluppatore Python incontrerà. Padroneggiare l'arte della gestione di errori ed eccezioni è una parte fondamentale per diventare un solido programmatore Python. Approfondisci altre tecniche di programmazione funzionale e le basi del codice con i nostri percorsi di competenze Python Programming e Python Fundamentals. Dai un'occhiata anche al nostro tutorial Insiemi in Python e teoria degli insiemi per scoprire concetti correlati. 

Javier Canales Luna

Autore

Javier Canales Luna

Sono una data analyst freelance e collaboro con aziende e organizzazioni di tutto il mondo in progetti di data science. Sono anche un'insegnante di data science con oltre 2 anni di esperienza. Scrivo regolarmente articoli su temi legati alla data science in inglese e spagnolo, alcuni dei quali sono stati pubblicati su siti affermati come DataCamp, Towards Data Science e Analytics Vidhya. Come data scientist con un background in scienze politiche e diritto, il mio obiettivo è lavorare all'intersezione tra politiche pubbliche, diritto e tecnologia, sfruttando la forza delle idee per promuovere soluzioni e narrazioni innovative che ci aiutino ad affrontare le sfide urgenti, in primis la crisi climatica. Mi considero autodidatta, una persona in continuo apprendimento e una convinta sostenitrice dell'approccio multidisciplinare. Non è mai troppo tardi per imparare cose nuove.

Argomenti

Correlato