Excepciones en Python

controlar excepciones en python

Las excepciones en Python son muy sencillas de manejar o controlar usando la estructura try-except. Adem谩s se pueden definir nuevas excepciones f谩cilmente.

Qu茅 es una excepci贸n en Python

Los errores en tiempo de ejecuci贸n se denominan聽excepciones, incluso si la declaraci贸n o expresi贸n es sint谩cticamente correcta, puede generar un error cuando se intenta ejecutarla.

Un ejemplo de excepci贸n es la divisi贸n entre 0, como se muestra a continuaci贸n:

>>> 10 * (1/0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero

El mensaje mostrado se puede dividir en lo siguiente:

  • La 煤ltima l铆nea de los mensajes de error indica qu茅 sucedi贸.
  • La cadena mostrada como tipo de la excepci贸n es el nombre de la excepci贸n predefinida que ocurri贸.
  • El resto de la l铆nea provee un detalle basado en el tipo de la excepci贸n y qu茅 la caus贸.

La lista detallada de excepciones definidas en Python puedes verla aqu铆.

驴Cu谩l es la diferencia entre un error de sintaxis y un excepci贸n? Pues un error de sintaxis es un uso incorrecto del lenguaje, es decir, expresar de forma incorrecta una estructura.

En cambio, una excepci贸n se produce cuando el programa se esta ejecutando. Por ejemplo si pedimos por teclado un n煤mero entero y realizamos una operaci贸n sin convertir la cadena recibida en un n煤mero se producir谩 una excepci贸n. (Puedes verlo en este post)

Controlar excepciones en Python

En Python, al igual que otros lenguajes como Java es posible controlar excepciones, para que el programa este preparado y ejecute unas instrucciones concretas cuando se produzcan excepciones.

En el siguiente c贸digo estamos viendo de forma pr谩ctica el ejemplo anterior, leer por teclado un n煤mero entero controlando la posible excepci贸n ValueError:

while True:
    try:
        x = int(input("Por favor ingrese un n煤mero \n> "))
        break
    except ValueError:
        print("Oops! No era v谩lido. Intente nuevamente \n>")

Una versi贸n recursiva de este c贸digo puedes verla en la siguiente publicaci贸n:

C贸mo funciona la estructura聽try-except聽en Python

La declaraci贸n try聽funciona de la siguiente manera:

  1. Se ejecuta el bloque try聽(el c贸digo entre las declaraci贸n try聽y except).
  2. Si no ocurre ninguna excepci贸n, el聽bloque except no se ejecuta y termina la ejecuci贸n de la declaraci贸n try.
  3. Si se produce una excepci贸n durante la ejecuci贸n del bloque try, el resto del bloque no se ejecuta y se produce lo siguiente:
    • El tipo coincide con la excepci贸n nombrada junto a la palabra reservada except, se ejecuta el聽bloque except, y la ejecuci贸n contin煤a despu茅s de la declaraci贸n try.
    • El tipo no coincide con la excepci贸n nombrada en el except, esta se pasa a declaraciones try de m谩s afuera. En caso de que, no se encuentra nada que la maneje, es una excepci贸n no manejada, y la ejecuci贸n finaliza con un mensaje de error.

Controlar varias excepciones con except en Python

Una declaraci贸n try聽puede tener m谩s de un except, para especificar manejadores para distintas excepciones, pero solo uno de ellos ser谩 ejecutado.

Un except聽tambi茅n puede nombrar m煤ltiples excepciones usando par茅ntesis, como por ejemplo:

try:
    pass
except (RuntimeError, ValueError, NameError):
    pass

Manejar todas las excepciones a la vez en Python

Al igual que un except puede nombrar espec铆ficamente que excepciones manejar, tambi茅n puede no nombrar ninguna de forma espec铆fica, consiguiendo que se manejen todas, es decir, cualquier excepci贸n que se produzca en el tryse manejar谩, como se muestra a continuaci贸n:

try:
    pass
except:
    pass

Bloque聽else聽controlando excepciones en Python

Las declaraciones try-except聽tienen un聽bloque else opcional, el cual, cuando est谩 presente, debe estar declarado a continuaci贸n a los except.

Este bloque es 煤til para aquel c贸digo que debe ejecutarse si el bloque try聽no genera una excepci贸n.

try:
    pass
except:
    pass
else:
    pass

Generar instancia con except en Python

El except puede especificar una variable despu茅s del nombre de excepci贸n. La variable se vincula a una instancia de excepci贸n con los argumentos almacenados en instance.args.

La instancia de excepci贸n define c贸mo __str__()聽para que se pueda mostrar los argumentos directamente, sin necesidad de hacer referencia a聽.args.

try:
    pass
except ValueError as inst:
    pass
else:
    pass

Lanzar excepciones en Python

La declaraci贸n raise聽permite al programador forzar que ocurra una excepci贸n espec铆fica. Por ejemplo:

>>> raise NameError('Problema')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: Problema

El 煤nico argumento a raise聽indica la excepci贸n que se generar谩. Tiene que ser una instancia de excepci贸n o una clase que hereda de Exception .

Si se pasa una clase de excepci贸n sin argumentos, la misma ser谩 instanciada impl铆citamente llamando a su constructor sin argumentos:

raise ValueError  # Equivalente a 'raise ValueError()'

Definir excepciones en Python

Los programas pueden nombrar sus propias excepciones creando una nueva clase que herede de聽Exception.

Las clases de Excepciones se pueden definir de la misma forma que cualquier otra clase, pero normalmente son simples, a menudo ofreciendo solo un n煤mero de atributos con informaci贸n sobre el error que leer谩 al manejar la excepci贸n.

Al crear un m贸dulo que puede lanzar distintos errores, una pr谩ctica com煤n es crear una clase base para excepciones definidas en ese m贸dulo y extenderla para crear clases excepciones espec铆ficas para distintas situaciones de error (m谩s informaci贸n aqu铆).

Ejemplo definiendo excepciones

Vamos a hacer un ejemplo en el que se quiere controlar la paridad de un n煤mero introducido por teclado. Para ello se definen las siguientes excepciones:

class Error(Exception): # Hereda de Exception
    """Clase base para excepciones en el m贸dulo."""
    pass


class parityError(Error): # Hereda de Error
    """Excepci贸n lanzada por errores cuando un numero no tiene
    la paridad que deseamos. La paridad de un n煤mero entero se 
    refiere a su atributo de ser par o impar.

    Atributos:
        num -- numero por el que ocurre el error
        mensaje -- explicaci贸n del error
    """

    def __init__(self, num, mensaje):
        self.num = num
        self.mensaje = mensaje

La clase聽Errorse crea por convenio, c贸mo hemos comentado antes, pero podr铆amos crear directamente la clase de nuestra excepci贸n que heredar谩 de聽Exception.

La idea con la excepci贸n creada es que la lancemos cuando detectemos un n煤mero con la paridad que no deseamos (La聽paridad聽de un聽n煤mero entero se refiere a su atributo de ser par o impar), como en el siguiente c贸digo:

try:
    n = int(input("Introduzca un numero entero \n> "))
    if n % 2 != 0:
        raise parityError(n,'El numero es impar')
except ValueError:
    print("No se ha introducido un numero")

En este caso lo que se quiere es un n煤mero par, con lo cual si el n煤mero es impar (el resto de dividir el n煤mero entre dos es distinto de 0) lanzamos la excepci贸n.

Cl谩usula finally聽en Python

La declaraci贸n try聽tiene otra cl谩usula opcional (finally) que intenta definir acciones de limpieza que deben ser ejecutadas bajo ciertas circunstancias. Por ejemplo:

>>> try:
...     raise KeyboardInterrupt
... finally:
...     print('Fin')
...
Fin
KeyboardInterrupt
Traceback (most recent call last):
  File "<stdin>", line 2, in ?

Una聽cl谩usula finally siempre es ejecutada antes de salir de la declaraci贸n try, ya sea cuando una excepci贸n haya ocurrido o no.

Cuando ocurre una excepci贸n en la cl谩usula try y no fue manejada por una cl谩usula except (o ocurri贸 en una cl谩usula except o else), es relanzada luego de que se ejecuta la cl谩usula finally.

El finally es tambi茅n ejecutado 鈥渁 la salida鈥 de cualquier otra cl谩usula de la declaraci贸n try siendo dejada via break, continue or return.


Espero que haya resultado de utilidad este art铆culo sobre las excepciones en Python, cualquier duda puedes hacerla en la secci贸n de comentarios y estar茅 encantado de responderla 馃檪

Deja un comentario