Clases de excepción y excepción

En general, una excepción es cualquier condición inusual. La excepción generalmente indica errores, pero a veces se colocan intencionalmente en el programa, en casos como la finalización anticipada de un procedimiento o la recuperación de una escasez de recursos. Hay una serie de excepciones integradas, que indican condiciones como leer más allá del final de un archivo o dividir por cero. Podemos definir nuestras propias excepciones llamadas excepción personalizada.

El manejo de excepciones le permite manejar los errores con elegancia y hacer algo significativo al respecto. El manejo de excepciones tiene dos componentes: "lanzar" y "atrapar".

Identificación de excepción (errores)

Cada error que ocurre en Python resulta en una excepción que dará lugar a una condición de error identificada por su tipo de error.

>>> #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.

Excepción de captura / captura

Cuando ocurre algo inusual en su programa y desea manejarlo usando el mecanismo de excepción, 'lanza una excepción'. Las palabras clave try y except se utilizan para detectar excepciones. Siempre que ocurre un error dentro de un bloque try, Python busca un bloque excepto que coincida para manejarlo. Si hay uno, la ejecución salta allí.

sintaxis

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

El código dentro de la cláusula try se ejecutará sentencia por sentencia.

Si ocurre una excepción, el resto del bloque try se saltará y se ejecutará la cláusula except.

try:
   some statement here
except:
   exception handling

Escribamos un código para ver qué sucede cuando no usa ningún mecanismo de manejo de errores en su programa.

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

El programa anterior funcionará correctamente siempre que el usuario ingrese un número, pero ¿qué sucede si los usuarios intentan colocar algún otro tipo de datos (como una cadena o una lista)?

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'"

Ahora ValueError es un tipo de excepción. Intentemos reescribir el código anterior con manejo de excepciones.

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)

Si ejecutamos el programa e ingresamos una cadena (en lugar de un número), podemos ver que obtenemos un resultado diferente.

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

Generación de excepciones

Para generar sus excepciones desde sus propios métodos, debe usar una palabra clave de aumento como esta

raise ExceptionClass(‘Some Text Here’)

Tomemos un ejemplo

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')

Ejecute el programa e ingrese un entero positivo.

Rendimiento esperado

Enter your age: 12
Entered Age is even

Pero cuando intentamos ingresar un número negativo obtenemos,

Rendimiento esperado

Enter your age: -2
Only positive integers are allowed

Creando una clase de excepción personalizada

Puede crear una clase de excepción personalizada ampliando la clase BaseException o la subclase de BaseException.

En el diagrama anterior, podemos ver que la mayoría de las clases de excepción en Python se extienden desde la clase BaseException. Puede derivar su propia clase de excepción de la clase BaseException o de su subclase.

Cree un nuevo archivo llamado NegativeNumberException.py y escriba el siguiente código.

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

El código anterior crea una nueva clase de excepción llamada NegativeNumberException, que consta de solo un constructor que llama al constructor de la clase principal usando super () __ init __ () y establece la edad.

Ahora, para crear su propia clase de excepción personalizada, escribirá un código e importará la nueva clase de excepción.

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')

Salida

Enter your age: -2
Only positive integers are allowed

Otra forma de crear una clase de excepción personalizada.

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)

Salida

Caught: My Useful Error Message!

Jerarquía de excepciones

La jerarquía de clases para las excepciones integradas es:

+-- 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