Eccezioni e classi di eccezione

In generale, un'eccezione è una condizione insolita. L'eccezione di solito indica errori, ma a volte vengono inseriti intenzionalmente nel programma, in casi come l'interruzione anticipata di una procedura o il ripristino da una carenza di risorse. Esistono numerose eccezioni integrate, che indicano condizioni come la lettura oltre la fine di un file o la divisione per zero. Possiamo definire le nostre eccezioni chiamate eccezioni personalizzate.

La gestione delle eccezioni consente di gestire gli errori con garbo e di fare qualcosa di significativo al riguardo. La gestione delle eccezioni ha due componenti: "lancio" e "cattura".

Identificazione dell'eccezione (errori)

Ogni errore che si verifica in Python risulta un'eccezione che sarà una condizione di errore identificata dal suo tipo di errore.

>>> #Exception
>>> 1/0
Traceback (most recent call last):
   File "<pyshell#2>", line 1, in <module>
      1/0
ZeroDivisionError: division by zero
>>>
>>> var = 20
>>> print(ver)
Traceback (most recent call last):
   File "<pyshell#5>", line 1, in <module>
      print(ver)
NameError: name 'ver' is not defined
>>> #Above as we have misspelled a variable name so we get an NameError.
>>>
>>> print('hello)

SyntaxError: EOL while scanning string literal
>>> #Above we have not closed the quote in a string, so we get SyntaxError.
>>>
>>> #Below we are asking for a key, that doen't exists.
>>> mydict = {}
>>> mydict['x']
Traceback (most recent call last):
   File "<pyshell#15>", line 1, in <module>
      mydict['x']
KeyError: 'x'
>>> #Above keyError
>>>
>>> #Below asking for a index that didn't exist in a list.
>>> mylist = [1,2,3,4]
>>> mylist[5]
Traceback (most recent call last):
   File "<pyshell#20>", line 1, in <module>
      mylist[5]
IndexError: list index out of range
>>> #Above, index out of range, raised IndexError.

Eccezione cattura / cattura

Quando si verifica qualcosa di insolito nel tuo programma e desideri gestirlo utilizzando il meccanismo delle eccezioni, "lanci un'eccezione". Le parole chiave try e tranne vengono utilizzate per rilevare le eccezioni. Ogni volta che si verifica un errore all'interno di un blocco try, Python cerca un blocco eccetto corrispondente per gestirlo. Se ce n'è uno, l'esecuzione salta lì.

sintassi

try:
   #write some code
   #that might throw some exception
except <ExceptionType>:
   # Exception handler, alert the user

Il codice all'interno della clausola try verrà eseguito istruzione per istruzione.

Se si verifica un'eccezione, il resto del blocco try verrà ignorato e verrà eseguita la clausola tranne.

try:
   some statement here
except:
   exception handling

Scriviamo un po 'di codice per vedere cosa succede quando non usi alcun meccanismo di gestione degli errori nel tuo programma.

number = int(input('Please enter the number between 1 & 10: '))
print('You have entered number',number)

Il programma sopra funzionerà correttamente fintanto che l'utente inserisce un numero, ma cosa succede se gli utenti cercano di inserire un altro tipo di dati (come una stringa o un elenco).

Please enter the number between 1 > 10: 'Hi'
Traceback (most recent call last):
   File "C:/Python/Python361/exception2.py", line 1, in <module>
      number = int(input('Please enter the number between 1 & 10: '))
ValueError: invalid literal for int() with base 10: "'Hi'"

Ora ValueError è un tipo di eccezione. Proviamo a riscrivere il codice precedente con la gestione delle eccezioni.

import sys

print('Previous code with exception handling')

try:
   number = int(input('Enter number between 1 > 10: '))

except(ValueError):
   print('Error..numbers only')
   sys.exit()

print('You have entered number: ',number)

Se eseguiamo il programma e inseriamo una stringa (invece di un numero), possiamo vedere che otteniamo un risultato diverso.

Previous code with exception handling
Enter number between 1 > 10: 'Hi'
Error..numbers only

Sollevare eccezioni

Per aumentare le tue eccezioni dai tuoi metodi devi usare la parola chiave raise come questa

raise ExceptionClass(‘Some Text Here’)

Facciamo un esempio

def enterAge(age):
   if age<0:
      raise ValueError('Only positive integers are allowed')
   if age % 2 ==0:
      print('Entered Age is even')
   else:
      print('Entered Age is odd')

try:
   num = int(input('Enter your age: '))
   enterAge(num)
except ValueError:
   print('Only positive integers are allowed')

Esegui il programma e inserisci un numero intero positivo.

Uscita prevista

Enter your age: 12
Entered Age is even

Ma quando proviamo a inserire un numero negativo otteniamo,

Uscita prevista

Enter your age: -2
Only positive integers are allowed

Creazione di una classe di eccezione personalizzata

È possibile creare una classe di eccezione personalizzata estendendo la classe BaseException o una sottoclasse di BaseException.

Dal diagramma sopra possiamo vedere la maggior parte delle classi di eccezione in Python che si estende dalla classe BaseException. È possibile derivare la propria classe di eccezione dalla classe BaseException o dalla sua sottoclasse.

Crea un nuovo file chiamato NegativeNumberException.py e scrivi il codice seguente.

class NegativeNumberException(RuntimeError):
   def __init__(self, age):
      super().__init__()
      self.age = age

Il codice precedente crea una nuova classe di eccezione denominata NegativeNumberException, che consiste solo nel costruttore che chiama il costruttore della classe genitore usando super () __ init __ () e imposta l'età.

Ora per creare la tua classe di eccezione personalizzata, scriverà del codice e importerà la nuova classe di eccezione.

from NegativeNumberException import NegativeNumberException
def enterage(age):
   if age < 0:
      raise NegativeNumberException('Only positive integers are allowed')

   if age % 2 == 0:
      print('Age is Even')

   else:
      print('Age is Odd')

try:
   num = int(input('Enter your age: '))
   enterage(num)
except NegativeNumberException:
   print('Only positive integers are allowed')
except:
   print('Something is wrong')

Produzione

Enter your age: -2
Only positive integers are allowed

Un altro modo per creare una classe di eccezione personalizzata.

class customException(Exception):
   def __init__(self, value):
      self.parameter = value

   def __str__(self):
      return repr(self.parameter)
try:
   raise customException('My Useful Error Message!')
except customException as instance:
   print('Caught: ' + instance.parameter)

Produzione

Caught: My Useful Error Message!

Gerarchia delle eccezioni

La gerarchia di classi per le eccezioni integrate è:

+-- SystemExit 
+-- KeyboardInterrupt 
+-- GeneratorExit 
+-- Exception 
+-- StopIteration 
+-- StopAsyncIteration 
+-- ArithmeticError 
| +-- FloatingPointError 
| +-- OverflowError 
| +-- ZeroDivisionError 
+-- AssertionError 
+-- AttributeError 
+-- BufferError 
+-- EOFError 
+-- ImportError 
+-- LookupError 
| +-- IndexError 
| +-- KeyError 
+-- MemoryError 
+-- NameError 
| +-- UnboundLocalError 
+-- OSError 
| +-- BlockingIOError 
| +-- ChildProcessError 
| +-- ConnectionError 
| | +-- BrokenPipeError 
| | +-- ConnectionAbortedError 
| | +-- ConnectionRefusedError 
| | +-- ConnectionResetError 
| +-- FileExistsError 
| +-- FileNotFoundError 
| +-- InterruptedError 
| +-- IsADirectoryError 
| +-- NotADirectoryError 
| +-- PermissionError 
| +-- ProcessLookupError 
| +-- TimeoutError 
+-- ReferenceError 
+-- RuntimeError 
| +-- NotImplementedError 
| +-- RecursionError 
+-- SyntaxError 
| +-- IndentationError
| +-- TabError 
+-- SystemError 
+-- TypeError 
+-- ValueError 
| +-- UnicodeError 
| +-- UnicodeDecodeError 
| +-- UnicodeEncodeError 
| +-- UnicodeTranslateError 
+-- Warning 
+-- DeprecationWarning 
+-- PendingDeprecationWarning 
+-- RuntimeWarning 
+-- SyntaxWarning 
+-- UserWarning 
+-- FutureWarning 
+-- ImportWarning 
+-- UnicodeWarning 
+-- BytesWarning 
+-- ResourceWarning