| Scopo | il modulo delle eccezioni definisce gli errori built-in usati attraverso tutta la libreria standard e dall'interprete. |
| Versione Python | 1.5 e successive |
A partire dal 1 gennaio 2021 le versioni 2.x di Python non sono piu' supportate. Ti invito a consultare la corrispondente versione 3.x dell'articolo per le versioni 3.x di Python
Nel passato, Ptyhon supportava come eccezioni sia semplici stringhe di messaggi che classi. Dalla versione 1.5, tutti i moduli della libreria standard usano le classi per le eccezioni. A partire da Python 2.5, le stringhe di eccezione generano un DeprecationWarning, ed il supporto per le stringhe di eccezione verrà rimosso in futuro.
Le classi delle eccezioni sono definite in una gerarchia, descritta nella documentazione della libreria standard. Oltre agli ovvi vantaggi di organizzazione, l'ereditarietà nelle eccezioni è utile perchè le eccezioni correlate possono essere intercettate tramite la loro classe base. Nella maggior parte dei casi, queste classi base non sono concepite per essere sollevate direttamente
E' la classe base per tutte le eccezioni. Implementa la logica per creare una rappresentazione sotto forma di stringa dell'eccezione usando str() dai parametri passati al costruttore
La classe base per le eccezioni che non risultano nella chiusura dell'applicazione in esecuzione. Tutte le eccezioni definite dall'utente dovrebbero usare Exception come classe base.
Classe base per le eccezioni built-in usate nella libreria standard
Classe base per errori relativi ad operazioni matematiche
Classe base per errori sollevati quando qualcosa non può essere trovato.
Classe base per errori che provengono al di fuori di Python (il sistema operativo, il filesystem ecc.).
AssertionError viene sollevata quando fallisce una istruzione di
assert
.
assert False, 'Asserzione fallita'
$ python exceptions_AssertionError_assert.py Traceback (most recent call last): File "exceptions_AssertionError_assert.py", line 1, inassert False, 'Asserzione fallita' AssertionError: Asserzione fallita<>
Viene anche usata nel modulo
unittest
in metodi tipo
failIf()
class AssertionExample(unittest.TestCase):
def test(self):
self.failUnless(False)
unittest.main()
$ python exceptions_AssertionError_unittest.py
F
======================================================================
FAIL: test (__main__.AssertionExample)
----------------------------------------------------------------------
Traceback (most recent call last):
File "exceptions_AssertionError_unittest.py", line 6, in test
self.failUnless(False)
AssertionError
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (failures=1)
Quando fallisce un riferimento od una assegnazione ad un attributo, viene sollevata AttributeError.
Ad esempio, quando si tenta di referenziare un attributo che non esiste:
class NoAttributes(object):
pass
o = NoAttributes()
print o.attribute
$ python exceptions_AttributeError.py Traceback (most recent call last): File "exceptions_AttributeError.py", line 7, inprint o.attribute AttributeError: 'NoAttributes' object has no attribute 'attribute'
O quando si tenta di modificare un attributo a sola lettura:
class MyClass(object):
@property
def attribute(self):
return "Questo è il valore dell'attributo"
o = MyClass()
print o.attribute
o.attribute = 'Nuovo valore'
$ python exceptions_AttributeError_assignment.py Questo è il valore dell'attributo Traceback (most recent call last): File "exceptions_AttributeError_assignment.py", line 13, ino.attribute = 'Nuovo valore' AttributeError: can't set attribute
EOFError viene sollevata quando una funzione built-in tipo
input()
o
raw_input()
non leggono alcun dato prima di trovare la fine del flusso di input. I metodi di file come
read()
restituiscono una stringa vuota alla fine del file.
while True:
data = raw_input('prompt:')
print 'LEGGO:', data
$ echo Ciao | python exceptions_EOFError.py prompt:LEGGO: Ciao prompt:Traceback (most recent call last): File "exceptions_EOFError.py", line 6, indata = raw_input('prompt:') EOFError: EOF when reading a line
Viene sollevata dalle operazioni con virgola mobile che risultano in errori, quando il controllo degli errori in virgola mobile (fpectl) è attivo. Per abilitare
fpectl
occorre che l'interprete sia compilato con il flag
..with-fpectl
. L'uso di fpectl è sconsigliato nella
documentazione della libreria standard
import math
import fpectl
print 'Controllo disattivato:', math.exp(1000)
fpectl.turnon_sigfpe()
print 'Control attivato:', math.exp(1000)
Sollevata all'interno di un generatore, quando viene chiamato il metodo
close()
del generatore.
def my_generator():
try:
for i in range(5):
print 'Trattengo', i
yield i
except GeneratorExit:
print 'Uscita prematura'
g = my_generator()
print g.next()
g.close()
$ python exceptions_GeneratorExit.py Trattengo 0 0 Uscita prematura
Sollevata quando fallisce una operazione di input od output, ad esempio se il disco è pieno, od un file di input non esiste.
f = open('/non/esiste', 'r')
$ python exceptions_IOError.py Traceback (most recent call last): File "exceptions_IOError.py", line 5, inf = open('/non/esiste', 'r') IOError: [Errno 2] No such file or directory: '/non/esiste'
Sollevata quando un modulo, od un membro di un modulo, non può essere importato. Sono poche le condizioni laddove ImportError possa essere sollevata:
1. Se un modulo non esiste.
import modulo_non_esiste
$ python exceptions_ImportError_nomodule.py Traceback (most recent call last): File "exceptions_ImportError_nomodule.py", line 4, inimport modulo_non_esiste ImportError: No module named modulo_non_esiste
2. Se si usa
from X import Y
e Y non si trova all'interno del modulo X
from exceptions import NomeFasullo
$ python exceptions_ImportError_missingname.py Traceback (most recent call last): File "exceptions_ImportError_missingname.py", line 4, infrom exceptions import NomeFasullo ImportError: cannot import name NomeFasullo
Sollevata quando il riferimento di una sequenza è fuori dai limiti
my_seq = [ 0, 1, 2 ]
print my_seq[3]
$ python exceptions_IndexError.py Traceback (most recent call last): File "exceptions_IndexError.py", line 5, inprint my_seq[3] IndexError: list index out of range
Viene sollevata quando un valore non viene trovato come chiave di un dizionario.
d = { 'a':1, 'b':2 }
print d['c']
$ python exceptions_KeyError.py Traceback (most recent call last): File "exceptions_KeyError.py", line 5, inprint d['c'] KeyError: 'c'
Viene sollevata ogniqualvolta l'utente preme Ctrl-C (o Canc) per interrompere un programma in esecuzione. Al contrario della maggior parte delle altre eccezioni, KeyboardInterrupt eredita direttamente da BaseException per evitare di venire intercettata da gestori delle eccezioni globali che catturano Exception.
try:
print 'Premere Invio o Ctrl-C:',
ignored = raw_input()
except Exception, err:
print 'Eccepezione catturata:', err
except KeyboardInterrupt, err:
print 'Catturato KeyboardInterrupt'
else:
print 'Nessuna eccezione'
$ python exceptions_KeyboardInterrupt.py Premere Invio o Ctrl-C: ^CCatturato KeyboardInterrupt
Se il programma esaurisce la memoria ed è possibile recuperarne (ad esempio eliminando alcuni oggetti), viene sollevata MemoryError.
import itertools
# Tentativo di creare un MemoryError allocando molta memoria
l = []
for i in range(3):
try:
for j in itertools.count(1):
print i, j
l.append('*' * (2**30))
except MemoryError:
print '(errore, si svuota la lista esistente)'
l = []
$ python exceptions_MemoryError.py 0 1 0 2 (errore, si svuota la lista esistente) 1 1 1 2 (errore, si svuota la lista esistente) 2 1 2 2 (errore, si svuota la lista esistente)
Viene sollevata quando nel proprio codice ci sono riferimenti ad un nome che non esiste nel contesto corrente. Ad esempio un nome di variabile non definita.
def func():
print nome_sconosciuto
func()
$ python exceptions_NameError.py Traceback (most recent call last): File "exceptions_NameError.py", line 7, infunc() File "exceptions_NameError.py", line 5, in func print nome_sconosciuto NameError: global name 'nome_sconosciuto' is not defined
Le classi base definite dall'utente possono sollevare NotImplementedError per indicare che un metodo od un comportamento deve essere definito nella sottoclasse, simulando una interfaccia
class BaseClass(object):
"""Definisce l'interfaccia"""
def __init__(self):
super(BaseClass, self).__init__()
def do_something(self):
"""L'interfaccua, non implementata"""
raise NotImplementedError(self.__class__.__name__ + '.fa_qualcosa')
class SubClass(BaseClass):
"""Implementa interfaccia"""
def do_something(self):
"""fa davvero qualcosa"""
print self.__class__.__name__ + ' facendo qualcosa!'
SubClass().do_something()
BaseClass().do_something()
$ python exceptions_NotImplementedError.py SubClass facendo qualcosa! Traceback (most recent call last): File "exceptions_NotImplementedError.py", line 19, inBaseClass().do_something() File "exceptions_NotImplementedError.py", line 10, in do_something raise NotImplementedError(self.__class__.__name__ + '.fa_qualcosa') NotImplementedError: BaseClass.fa_qualcosa
Funge da classe di errore per il modulo os , e viene sollevato quando l'errore ritorna da una funzione specifica di os
import os
for i in range(10):
print i, os.ttyname(i)
$ python exceptions_OSError.py 0 /dev/pts/2 1 /dev/pts/2 2 /dev/pts/2 3 Traceback (most recent call last): File "exceptions_OSError.py", line 7, inprint i, os.ttyname(i) OSError: [Errno 9] Bad file descriptor
Quando una operazione matematica eccede i limiti del tipo di variabile, viene sollevata OverflowError. Gli interi long allocano tanto più spazio quanto più crescono i loro valori, quindi finiscono per sollevare MemoryError. La gestione degli errori in virgola mobile non è standardizzata, quindi i valori a virgola mobile non sono verificati. Gli interi normali sono convertiti nei corrispondenti valori long quando necessario.
import sys
print 'Intero normale: (maxint=%s)' % sys.maxint
try:
i = sys.maxint * 3
print 'Nessun overflow per ', type(i), 'i =', i
except OverflowError, err:
print 'Overflow a ', i, err
print
print 'Intero lungo:'
for i in range(0, 100, 10):
print '%2d' % i, 2L ** i
print
print 'Valori a virgola mobile:'
try:
f = 2.0**i
for i in range(100):
print i, f
f = f ** 2
except OverflowError, err:
print 'Overflow dopo ', f, err
$ python exceptions_OverflowError.py Intero normale: (maxint=2147483647) Nessun overflow peri = 6442450941 Intero lungo: 0 1 10 1024 20 1048576 30 1073741824 40 1099511627776 50 1125899906842624 60 1152921504606846976 70 1180591620717411303424 80 1208925819614629174706176 90 1237940039285380274899124224 Valori a virgola mobile: 0 1.23794003929e+27 1 1.53249554087e+54 2 2.34854258277e+108 3 5.5156522631e+216 Overflow dopo 5.5156522631e+216 (34, 'Numerical result out of range')
Quando si usa un proxy weakref per accedere ad un oggetto che è già stato recuperato dalla garbage collection, si genera un errore ReferenceError.
import gc
import weakref
class ExpensiveObject(object):
def __init__(self, name):
self.name = name
def __del__(self):
print '(Elimino %s)' % self
obj = ExpensiveObject('obj')
p = weakref.proxy(obj)
print 'PRIMA:', p.name
obj = None
print 'DOPO :', p.name
$ python exceptions_ReferenceError.py PRIMA: obj (Elimino <__main__.ExpensiveObject object at 0xb7855c8c>) DOPO : Traceback (most recent call last): File "exceptions_ReferenceError.py", line 18, inprint 'DOPO :', p.name ReferenceError: weakly-referenced object no longer exists
Una eccezione RuntimeError si usa quando non si può applicare nessun'altra eccezione più specifica. L'interprete solleva questa eccezione raramente, ma qualche porzione di codice utente lo può fare.
Quando un iterator ha concluso il ciclo, il suo metodo
next()
solleva StopIteration. Questa eccezione non è considerata un errore.
l=[0,1,2]
i=iter(l)
print i
print i.next()
print i.next()
print i.next()
print i.next()
$ python exceptions_StopIteration.py0 1 2 Traceback (most recent call last): File "exceptions_StopIteration.py", line 11, in print i.next() StopIteration
Ogni volta che l'analizzatore sintattico del linguaggio ( parser ) trova codice sorgente che non riesce a comprendere viene sollevata SyntaxError. Può succedere quando si importa un modulo, si chiama exec() od eval(). Gli attributi dell'eccezione possono essere usati per trovare esattamente quale parte del testo in input ha causato l'eccezione.
try:
print eval('cinque volte tre')
except SyntaxError, err:
print 'Errore di sintassi %s (%s-%s): %s' % \
(err.filename, err.lineno, err.offset, err.text)
print err
$ python exceptions_SyntaxError.py Errore di sintassi(1-12): cinque volte tre invalid syntax ( , line 1)
Quando l'errore capita nell'interprete stesso ed esiste qualche possibilità di continuare l'esecuzione con successo, si solleva un SystemError. SystemError in genere indica un baco nell'interprete e dovrebbe essere notificato al curatore.
Quando si chiama
sys.exit()
, invece di uscire immediatamente viene sollevata SystemExit. Questo consente alla parte di codice di "pulizia" che si strova nel blocco
try:finally
di essere eseguita, ed ai chiamanti (come i debugger ed i framework di test) di catturare l'eccezione ed evitare di uscire.
Le eccezioni TypeError sono causate combinando tipi di oggetti sbagliati, o chiamando una funzione con il tipo di oggetto sbagliato.
result = ('tuple',) + 'string'
$ python exceptions_TypeError.py Traceback (most recent call last): File "exceptions_TypeError.py", line 4, inresult = ('tuple',) + 'string' TypeError: can only concatenate tuple (not "str") to tuple
E' un tipo di NameError specifico per i nomi di variabili locali.
def throws_global_name_error():
print unknown_global_name
def throws_unbound_local():
local_val = local_val + 1
print local_val
try:
throws_global_name_error()
except NameError, err:
print 'Errore di nome globale:', err
try:
throws_unbound_local()
except UnboundLocalError, err:
print 'Errore di nome locale:', err
La differenza tra NameError globale e UnboundLocal è il modo nel quale viene usato il nome. Visto che il nome "local_val" si trova nella parte sinistra di una espressione, viene interpretato come nome di variabile locale.
$ python exceptions_UnboundLocalError.py Errore di nome globale: global name 'unknown_global_name' is not defined Errore di nome locale: local variable 'local_val' referenced before assignment
UnicodeError è una sottoclasse di ValueError e viene sollevata quando si verifica un problema di Unicode. Ci sono sottoclassi separate per UnicodeEncodeError, UnicodeDecodeError, e UnicodeTranslateError.
ValueError viene usata quando una funzione riceve un dato del tipo giusto ma del valore non valido.
print chr(1024)
$ python exceptions_ValueError.py Traceback (most recent call last): File "exceptions_ValueError.py", line 4, inprint chr(1024) ValueError: chr() arg not in range(256)
Quando zero è il denominatore di una operazione di divisione, viene sollevata ZeroDivisionError.
print 1/0
exceptions_ZeroDivisionError.py
Si sono anche parecchie eccezioni definite per l'uso con il modulo warnings
Vedere anche: