Python – Captura selectiva de excepciones

Objetivo: mostrar cómo capturar selectivamente las excepciones en Python dependiendo de su tipo.

En el artículo anterior introdujimos el concepto de excepción en Python y aprendimos a proteger a prueba de bombas un determinado bloque de código utilizando la estructura try/except. El bloque a proteger lo recogíamos en la sección try y, si algo inesperado (una excepción) ocurría dentro de él, las instrucciones contenidas en la sección except se ocupaban de su tratamiento.

Recuperemos nuestra robusta división entera:

while True:
    try:
        dividendo = int(input('Introduce el dividendo: '))
        divisor = int(input('Introduce el divisor: '))
        print('El cociente de la división de ambos números es', dividendo//divisor)
    except:
        print('Eso no ha estado bien, pero no pasa nada')
        print('Vuelve a intentarlo')

Si y sólo si sucede una excepción dentro de la sección try, el bloque de la sección except será ejecutado.

En particular, el código está vacunado ante excepciones como, por ejemplo:

ZeroDivisionError: si introducimos un cero como divisor, la división dejará de existir.

ValueError: si en lugar de introducir números escribimos caracteres, la función int() no podrá realizar la conversión.

KeyboardInterrupt: si tecleamos Ctrl-C el programa será abortado.

Pero, ¿y si queremos controlar la captura de excepciones de un modo más selectivo? Por ejemplo, ¿cómo haríamos si sólo queremos dejar protegido el código ante un eventual ZeroDivisionError?

Basta con especificar el tipo de excepción en la claúsula except. Veámoslo:

while True:
    try:
        dividendo = int(input('Introduce el dividendo: '))
        divisor = int(input('Introduce el divisor: '))
        print('El cociente de la división de ambos números es', dividendo//divisor)
    except ZeroDivisionError:
        print('Eso no ha estado bien, pero no pasa nada')
        print('Vuelve a intentarlo')

>>> 
Introduce el dividendo: 10
Introduce el divisor: 0
Eso no ha estado bien, pero no pasa nada
Vuelve a intentarlo
Introduce el dividendo: 
Traceback (most recent call last):
  File "C:/Users/javier/Desktop/borrable.py", line 3, in <module>
    dividendo = int(input('Introduce el dividendo: '))
KeyboardInterrupt

Como vemos, la excepción ZeroDivisionError ha sido capturada, pero no KeyboardInterrupt, ocasionada al teclear Ctrl-C con la intención de terminar la ejecución del programa.

Vayamos un paso más adelante. Escribamos ahora código que proteja no sólo de ZeroDivisionError, sino también de ValueError. Para ello, es suficiente con introducir ambas excepciones, separadas con una coma y entre paréntesis junto a la palabra except:

while True:
    try:
        dividendo = int(input('Introduce el dividendo: '))
        divisor = int(input('Introduce el divisor: '))
        print('El cociente de la división de ambos números es', dividendo//divisor)
    except (ZeroDivisionError, ValueError):
        print('Eso no ha estado bien, pero no pasa nada')
        print('Vuelve a intentarlo')

Comprobémoslo:

>>> 
Introduce el dividendo: 12
Introduce el divisor: 0
Eso no ha estado bien, pero no pasa nada
Vuelve a intentarlo
Introduce el dividendo: 12
Introduce el divisor: abcde
Eso no ha estado bien, pero no pasa nada
Vuelve a intentarlo
Introduce el dividendo: 12
Introduce el divisor: 4
El cociente de la división de ambos números es 3
Introduce el dividendo: 
Traceback (most recent call last):
  File "C:/Users/javier/Desktop/borrable.py", line 3, in <module>
    dividendo = int(input('Introduce el dividendo: '))
KeyboardInterrupt

Ctrl-C ha podido interrumpir el programa, pero no la división por cero ni el uso de letras en lugar de números.

El código siguiente ejecutará un tratamiento diferente según la excepción que se produzca. Observa el uso de varias claúsulas except:


while True:
    try:
        dividendo = int(input('Introduce el dividendo: '))
        divisor = int(input('Introduce el divisor: '))
        print('El cociente de la división de ambos números es', dividendo//divisor)
    except ZeroDivisionError:
        print('¡No, no, la división por cero no está permitida!')
    except ValueError:
        print('¡Ojo, presta atención e introduce sólo números!')

No sólo hemos capturado selectivamente las excepciones ZeroDivisionError y ValueError, sino que, además, el programa responderá de modo distinto según cuál suceda. Obsérvalo:

>>> 
Introduce el dividendo: 10
Introduce el divisor: 0
¡No, no, la división por cero no está permitida!
Introduce el dividendo: 10
Introduce el divisor: abcde
¡Ojo, presta atención e introduce sólo números!
Introduce el dividendo: 
Traceback (most recent call last):
  File "C:/Users/javier/Desktop/borrable.py", line 3, in <module>
    dividendo = int(input('Introduce el dividendo: '))
KeyboardInterrupt

Hemos salido del bucle infinito pulsando Ctrl-C, pues KeyboardInterrupt no ha sido capturada.

Naturalmente, puedes incluir tantos except personalizados como excepciones desees tratar.

Aún podemos rizar el rizo…

Imagina que, además de lo que hemos hecho en el ejemplo anterior, en el que hemos capturado y tratado de modo diferente dos excepciones, queremos programar una respuesta general para cualquier otra excepción. Agregamos, simplemente, una nueva claúsula except genérica que no incluya ningún nombre de excepción:

while True:
    try:
        dividendo = int(input('Introduce el dividendo: '))
        divisor = int(input('Introduce el divisor: '))
        print('El cociente de la división de ambos números es', dividendo//divisor)
    except ZeroDivisionError:
        print('¡No, no, la división por cero no está permitida')
    except ValueError:
        print('¡Ojo, presta atención e introduce sólo números!')
    except:
        print('No sé qué has hecho, pero vuelve a intentarlo')

Y ahora:

>>> 
Introduce el dividendo: 10
Introduce el divisor: 0
¡No, no, la división por cero no está permitida
Introduce el dividendo: 10
Introduce el divisor: abcde
¡Ojo, presta atención e introduce sólo números!
Introduce el dividendo: 10
Introduce el divisor: 
No sé qué has hecho, pero vuelve a intentarlo
Introduce el dividendo: 

En el tercer intento hemos pulsado Ctrl-C, por eso aparece el mensaje que hemos reservado para otras excepciones.

El tratamiento genérico debe figurar siempre en último lugar, después de los especializados. De lo contrario, el programa devolverá un error sintáctico al tratar de ejecutarlo. Y me temo que ese tipo de errores no hay try/except que los capture.

Esto se ha puesto interesante, pero aún hay mucho más que decir sobre el tratamiento de excepciones. Permanece atento…

Javier Montero Gabarró


Python – Captura selectiva de excepciones


El texto de este artículo se encuentra sometido a una licencia Creative Commons del tipo CC-BY-NC-ND (reconocimiento, no comercial, sin obra derivada, 3.0 unported)


El Club del Autodidacta


Consulta el índice completo de artículos relacionados con Python.

6 opiniones en “Python – Captura selectiva de excepciones”

  1. Estaba buscando un tutorial de Python y me encuentro este blog. De verdad que me ha gustado bastante. No solo encontré información sobre Python, también hay entradas sobre música, Musescore y otros tópicos bastante interesantes.
    De verdad que me ha ayudado mucho 😀

  2. hola, no se nada de programacion pero esto de python me suena. uso un programa para grabar que se llama reaper, bueno y entre tantas utilidades que trae reaper me tuve que descargar python 3.4 creo que es. para ejecutar algunos scripts. en fin saludos

  3. Hola, gracias por tus tutoriales sobre python, me gusta mucho la forma en que lo explicas, pero tengo una duda con las excepciones, ¿Se puede imprimir imformacion a cerca de la excepcion, asi como en Java?, algo asi como esto: System.out.println(ex.getMessage()); pues he buscado pero no encuentro nada de ello. Muchas gracias, espero puedas responder mi pregunta. Hasta luego!

Responder a aeelinn Cancelar respuesta