Manejar excepciones en Python

python error

Si lo que necesitas es manejar excepciones en Python, para adecuar tu código a determinada exigencias, el lenguaje nos da suficientes herramientas para ello.

En este ejemplo que hemos tomado de aquí , se le pide al usuario una entrada hasta que ingrese un entero válido; sin embargo también se le permite un modo de interrumpir el programa la ejecución del programa, usando Control-C.

Esta interrupción se recoge generando la excepción KeyboardInterrupt.

>>> while True:
...     try:
...         x = int(input("Please enter a number: "))
...         break
...     except ValueError:
...         print("Oops!  That was no valid number.  Try again...")
...

Las excepciones se manejan con las sentencias try y except

Manejar las excepciones

La sentencia try funciona de la siguiente manera.

  • Primero, se ejecuta la cláusula try  que ejecuta el código que exista entre entre las palabras reservadas try y  except).
  • Si no ocurre ninguna excepción, la cláusula except() se omite y la ejecución de la cláusula try finaliza.
  • Si una excepción ocurre durante la ejecución de try, el resto de la clausula se salta.
  • En ese caso si su tipo coincide con la excepción nombrada después de la palabra clave except, se ejecuta la cláusula except, y luego la ejecución continúa después del bloque try / except.

Si la excepción que ocurre no coincide con la excepción nombrada en la cláusula except,  se pasa a ejecutar las sentencias try externas; y si no se encontraran, entonces el interprete considerará excepción como una excepcion no controlada y  detendrá la ejecución, lanzando un mensaje como el que aparece en el ejemplo.  

Una declaración try() puede tener más de una cláusula except, para especificar manejadores para diferentes excepciones que corresponden a un mismo try().

No obstante, como máximo, se ejecutará un controlador.

Los manejadores solo manejan las excepciones que ocurren en la cláusula try correspondiente.

Una cláusula except puede nombrar múltiples excepciones, empleando  una tupla entre paréntesis, por ejemplo:

... except (RuntimeError, TypeError, NameError):
...     pass

Si declaramos una clase en una cláusula except esta será  compatible con una excepción, si es la misma clase o una clase base de la misma.

Esto no funciona al revés, o sea  una cláusula except que enumera una clase derivada no es compatible con una clase base.

Por ejemplo, el siguiente código imprimirá B, C, D en ese orden:

class B(Exception):
    pass

class C(B):
    pass

class D(C):
    pass

for cls in [B, C, D]:
    try:
        raise cls()
    except D:
        print("D")
    except C:
        print("C")
    except B:
        print("B")

Si invirtiéramos las cláusulas, colocando except B primero, obtendríamos como resultado B,B,B, ya que una vez que el bucle alcanza el primera coincidencia se lanza la excepción.

Todas las excepciones heredan de BaseException,  de modo que puede emplearse como comodín.

No obstante dado que las excepciones pueden enmascar un error de programación real , es recomendable emplearlo con cuidado.

La instrucción try ... except tiene una cláusula else opcional, que, cuando está presente, seguir a las cláusulas except.

Es útil para el código que debe ejecutarse si la cláusula try no genera una excepción. Por ejemplo:

De este modo else() evita capturar accidentalmente una excepción que no fue generada por el código que está protegido por la declaración try … except.

Cuando ocurre una excepción, puede tener un valor asociado, también conocido como el argumento de la excepción. La presencia y el tipo de argumento depende del tipo de excepción.

La cláusula except puede especificar una variable después del nombre de la excepción.

Dicha variable está vinculada a una instancia de excepción con los argumentos almacenados en instance.args.

Por conveniencia, la instancia de excepción define __str __ () para que los argumentos se puedan imprimir directamente sin tener que hacer referencia a .args.

También se puede crear una instancia de una excepción antes de generarla y agregarle los atributos que desee.

>>> try:
...     raise Exception('spam', 'eggs')
... except Exception as inst:
...     print(type(inst))    # instancia de la excepcion
...     print(inst.args)     # argumentos guardados en .args
...     print(inst)          # __str__ permite args para que          
                             #sean imprimidos directamente
...                          # pero pueden ser sobrescritos 
                             #en las subclases de la            
                             #excepcion
...     x, y = inst.args     # desempaquetando  args
...     print('x =', x)
...     print('y =', y)
...
<class 'Exception'>
('spam', 'eggs')
('spam', 'eggs')
x = spam
y = eggs

Cuando una excepción tiene argumentos, estos se imprimen en la parte final del mensaje para las excepciones no gestionadas (“Unhandled exception”).

Los controladores de excepciones no solo manejan las excepciones si ocurren inmediatamente en la cláusula try, sino también si ocurren dentro de funciones que se llaman (incluso indirectamente) en la cláusula try.

Por ejemplo:

>>> def this_fails():
...     x = 1/0
...
>>> try:
...     this_fails()
... except ZeroDivisionError as err:
...     print('Handling run-time error:', err)
...
Handling run-time error: division by zero

…. siempre habrá poesía

J. A. Becquer