Excepciones.
Por definición las excepciones son errores que se producen durante la ejecución del código y que no son esperadas por el usuario.
Un ejemplo típico es el tener un programa que divide dos números y tratamos de dividir uno de ellos entre cero.
> print(8/0)
Traceback (most recent call last):
File "<string>", line 1, in <module>
ZeroDivisionError: division by zero
try:
[instrucciones o código a ejecutar.]
except <tipo de excepción>, <tipo de excepción>...:
[instrucciones o código a ejecutar si ocurre la excepción señalada. En
el caso de que no se indique una excepción en concreto y se deje en
blanco, la excepción se ejecutará con cualquier tipo de error. También
se pueden poner varios except seguidos y saltará el código del error
correspondiente.]
except: # Si ponemos excepciones especificas, está última debe ser la
genérica para recoger las que no se recojan previamente. La genérica
SIEMPRE DEBE SER LA ÚLTIMA en colocarse.
else: # esta instrucción es opcional
[código a ejecutar solamente si no ocurre ninguna excepción.]
finally: # este instrucción es opcional
[código a ejecutar tanto si ocurren excepciones como si no.]
def division(numero_1, numero_2):
try:
print(numero_1/numero_2)
except ZeroDivisionError:
print("No puedes dividir un número entre cero.")
return "operación errónea"
else:
print("División realizada correctamente.")
finally:
return "Función terminada."
print(division(8,4))
2.0
División realizada correctamente.
Función terminada.
print(division(8,0))
No puedes dividir un número entre cero.
Función terminada.
try:
print(8/0)
finally:
print("Ha habido un error")
Ha habido un error
Traceback (most recent call last):
File "<string>", line 2, in <module>
ZeroDivisionError: division by zero
>
Excepciones propias - RAISE -
# Vamos a dividir 8 entre un número pero no queremos que se pueda
# utilizar el cero como divisor.
divisor = int(input("Introduce un numero como divisor: "))
if divisor == 0:
raise ZeroDivisionError("¡No se puede dividir entre cero!")
print(8/divisor)
Introduce un numero como divisor: 0
Traceback (most recent call last):
File "<string>", line 5, in <module>
ZeroDivisionError: ¡No se puede dividir entre cero!
>
La instrucción assert.
def raiz_cuadrada(numero):
return pow(numero, 0.5)
resultado = raiz_cuadrada(25)
assert resultado == 5.0, "La función no funciona."
print("el calculo es correcto")
el calculo es correcto >
def raiz_cuadrada(numero):
return pow(numero, 0.6)
resultado = raiz_cuadrada(25)
assert resultado == 5.0, "La función no funciona"
print("el calculo es correcto")
Traceback (most recent call last):
File "<string>", line 5, in <module>
AssertionError: La función no funciona
Las excepciones son Clases.
Los ejemplos anteriores se centraron en detectar un tipo específico de excepción y responder de manera apropiada. Ahora vamos a profundizar más y mirar dentro de la excepción misma.
Probablemente no te sorprenderá saber que las excepciones son clases. Además, cuando se genera una excepción, se crea una instancia de un objeto de la clase y pasa por todos los niveles de ejecución del programa, buscando el bloque "except" que está preparado para tratar con la excepción.
Tal objeto lleva información útil que puede ayudarte a identificar con precisión todos los aspectos de la situación pendiente. Para lograr ese objetivo, Python ofrece una variante especial de la cláusula de excepción: puedes encontrarla en el siguiente código.
try: int("Hola") except Exception as e: print(e) print(e.__str__())
Salida:
invalid literal for int() with base 10: 'Hola' invalid literal for int() with base 10: 'Hola'
Como puedes ver, la sentencia
Nota: el alcance del identificador solo es dentro del
El ejemplo presenta una forma muy simple de utilizar el objeto recibido: simplemente imprímelo (como puedes ver, la salida es producida por el método del objeto
Se imprimirá el mismo mensaje si no hay un bloque
def imprimir_arbol_excepciones(estaclase, anidado = 0): if anidado > 1: print(" |" * (anidado - 1), end="") if anidado > 0: print(" +---", end="") print(estaclase.__name__) for subclass in estaclase.__subclasses__(): imprimir_arbol_excepciones(subclass, anidado + 1) imprimir_arbol_excepciones(BaseException)
BaseException +---Exception | +---TypeError | +---StopAsyncIteration | +---StopIteration | +---ImportError | | +---ModuleNotFoundError | | +---ZipImportError | +---OSError | | +---ConnectionError | | | +---BrokenPipeError | | | +---ConnectionAbortedError | | | +---ConnectionRefusedError | | | +---ConnectionResetError | | +---BlockingIOError | | +---ChildProcessError | | +---FileExistsError | | +---FileNotFoundError | | +---IsADirectoryError | | +---NotADirectoryError | | +---InterruptedError | | +---PermissionError | | +---ProcessLookupError | | +---TimeoutError | | +---UnsupportedOperation | | +---ItimerError | +---EOFError | +---RuntimeError | | +---RecursionError | | +---NotImplementedError | | +---_DeadlockError | +---NameError | | +---UnboundLocalError | +---AttributeError | +---SyntaxError | | +---IndentationError | | | +---TabError | +---LookupError | | +---IndexError | | +---KeyError | | +---CodecRegistryError | +---ValueError | | +---UnicodeError | | | +---UnicodeEncodeError | | | +---UnicodeDecodeError | | | +---UnicodeTranslateError | | +---UnsupportedOperation | +---AssertionError | +---ArithmeticError | | +---FloatingPointError | | +---OverflowError | | +---ZeroDivisionError | +---SystemError | | +---CodecRegistryError | +---ReferenceError | +---MemoryError | +---BufferError | +---Warning | | +---UserWarning | | +---DeprecationWarning | | +---PendingDeprecationWarning | | +---SyntaxWarning | | +---RuntimeWarning | | +---FutureWarning | | +---ImportWarning | | +---UnicodeWarning | | +---BytesWarning | | +---ResourceWarning +---GeneratorExit +---SystemExit +---KeyboardInterrupt
Anatomía detallada de las excepciones.
def print_args(args): lng = len(args) if lng == 0: print("") elif lng == 1: print(args[0]) else: print(str(args)) try: raise Exception except Exception as e: print(e, e.__str__(), sep = " : ", end = " : ") print_args(e.args) try: raise Exception("Mi excepción") except Exception as e: print(e, e.__str__(), sep = " : ", end = " : ") print_args(e.args) try: raise Exception("Mi", "excepción") except Exception as e: print(e, e.__str__(), sep = " : ", end = " : ") print_args(e.args)
: : Mi excepción : Mi excepción : Mi excepción ('Mi', 'excepción') : ('Mi', 'excepción') : ('Mi', 'excepción')
class MiDivisionEntreCeroError(ZeroDivisionError): pass def haz_la_division(mine): if mine: raise MiDivisionEntreCeroError("Peores Noticias") else: raise ZeroDivisionError("Malas Noticias") for modo in [False, True]: try: haz_la_division(modo) except ZeroDivisionError: print('División entre cero') for modo in [False, True]: try: haz_la_division(modo) except MiDivisionEntreCeroError: print('Mi división entre cero') except ZeroDivisionError: print('División entre cero original')
División entre cero
División entre cero
División entre cero original
Mi división entre cero
class PizzaError(Exception):
def __init__(self, pizza, mensaje):
Exception.__init__(self, mensaje)
self.pizza = pizza
class DemasiadoQueso(PizzaError):
def __init__(self, pizza, queso, mensaje)
super().__init__(pizza, mensaje)
self.queso = queso
class PizzaError(Exception):
def __init__(self, pizza, mensaje):
Exception.__init__(self, mensaje)
self.pizza = pizza
class DemasiadoQueso(PizzaError):
def __init__(self, pizza, queso, mensaje):
super().__init__(pizza, mensaje)
self.queso = queso
def haciendo_pizza(pizza, queso):
if pizza not in ['margarita','romana', 'calzone']:
raise PizzaError(pizza, "No existe tal pizza en el menú.")
if queso > 100:
raise DemasiadoQueso(pizza, queso, "Demasiado queso en la pizza.")
print("¡La pizza está lista!.")
for (pz, qs) in [('calzone', 10), ('margarita', 110), ('cazurra',20)]:
try:
haciendo_pizza(pz, qs)
except DemasiadoQueso as dmqs:
print(dmqs, ':', dmqs.queso)
except PizzaError as pe:
print(pe, ':', pe.pizza)
¡La pizza está lista!.
Demasiado queso en la pizza. : 110
No existe tal pizza en el menú. : cazurra
- Si removemos el bloque except DemasiadoQueso, todas las excepciones que se produzcan serán PizzaError.
- El remover el bloque que comienza con except PizzaError provocará que la excepción DemasiadoQueso no pueda ser manejada, y hará que el programa finalize.
class PizzaError(Exception): def __init__(self, pizza = 'desconocida', mensaje = ''): Exception.__init__(self, mensaje) self.pizza = pizza class DemasiadoQueso(PizzaError): def __init__(self, pizza = 'desconocida', queso = '>100', mensaje = ''): super().__init__(pizza, mensaje) self.queso = queso def haciendo_pizza(pizza, queso): if pizza not in ['margarita','romana', 'calzone']: raise PizzaError(pizza, "No existe tal pizza en el menú.") if queso > 100: raise DemasiadoQueso(pizza, queso, "Demasiado queso en la pizza.") print("¡La pizza está lista!.") for (pz, qs) in [('calzone', 10), ('margarita', 110), ('cazurra',20)]: try: haciendo_pizza(pz, qs) except DemasiadoQueso as dmqs: print(dmqs, ':', dmqs.queso) except PizzaError as pe: print(pe, ':', pe.pizza)
No hay comentarios:
Publicar un comentario