Manejo de excepciones en Python (A3C34C2D04)

Excepciones en Python

El lenguaje de programación Python distingue dos tipos de errores principales: i) los errores de sintaxis y ii) las excepciones. Los primeros ocurren debido a construcciones incorrectas a la hora de utilizar la sintaxis del lenguaje. El siguiente listado muestra un sencillo ejemplo, donde se puede apreciar cómo el intérprete de Python señala una posición cercana al potencial error (en este caso, la falta del carácter : después de ‘while True’). Las segundas, como ya se ha introducido previamente, responden a eventos que tienen lugar durante la ejecución de un programa, alterando de forma no deseada su flujo de ejecución estándar.

>>> while True print(“Aprendiendo Python”)
    File “<stdin>”, line 1
        while True print(“Aprendiendo Python”)
                    ^

SyntaxError: invalid syntax

Cuando se produce una excepción en Python, y no se controla, entonces el intérprete muestra el nombre de la excepción que se ha lanzado. Por ejemplo, el siguiente listado muestra la excepción ZeroDivisionError, definida por el propio lenguaje cuando se intenta dividir por 0.

>>> 7 / 0
Traceback (most recent call last):
    File “<stdin>”, line 1, in <module>
ZeroDivisionError: division by zero

Afortunadamente, es posible escribir programas en Python que manejen excepciones de forma adecuada. Para ello, es posible utilizar la sentencia try. Esta funciona de la siguiente forma:

1 |  En primer lugar, se ejecuta la cláusula try (las sentencias entre las palabras clave try y except).

2 |  Si no se produce ninguna excepción, la cláusula except se salta y finaliza la ejecución de la sentencia try.

3 |  Si se produce una excepción durante la ejecución de la cláusula try, se salta el resto de la cláusula. Entonces, si su tipo coincide con la excepción nombrada después de la palabra clave except, se ejecuta la cláusula except y la ejecución continúa después del bloque try/except.

4 |  Si ocurre una excepción que no coincide con la excepción nombrada en la cláusula except, se pasa a las sentencias try externas. Si no se encuentra un manejador para la excepción, entonces se trata de una excepción no manejada y la ejecución se detiene con un mensaje como el del listado anterior.

Una sentencia try puede tener más de una cláusula except, con el objetivo de especificar manejadores para diferentes excepciones. Por otro lado, la sentencia try tiene una cláusula else opcional que, cuando está presente, debe seguir a todas las cláusulas except. Esta cláusula else es útil para incluir el código que debe ejecutarse si la cláusula try no lanza una excepción. El siguiente fragmento de código muestra un ejemplo en el que se trata de abrir un archivo, cuyo nombre se almacena en mi_archivo. Si el archivo no existe, entonces se lanzaría una excepción del tipo OSError, capturada en la cláusula except. Si el archivo existe, entonces, en este ejemplo, se ejecutaría el código de la cláusula else, donde se imprime el número de líneas que tiene el archivo.

try:
    f = open(mi_archivo, “r”)
except OSError:
    print(“No se pudo abrir”, mi_archivo)
else:
    print(mi_archivo, “tiene”, len(f.readlines()), “líneas.”)
    f.close()

Es posible definir excepciones de usuario, es decir, excepciones cuya semántica está asociada al código que representa la solución a un problema concreto. Un ejemplo de excepción definida por el usuario, ya introducida anteriormente, podría contemplar el intento de almacenamiento de un número de teléfono que no tenga exactamente 9 dígitos. El siguiente listado muestra el código representativo de este ejemplo, en el que se puede apreciar la creación de la excepción FormatoDeNumeroNoValidoException, definida como una nueva clase en Python. Esta clase heredaría de la clase genérica Exception.

class FormatoDeNumeroNoValidoException(Exception):
    pass

numero = input(“Introduzca un número de teléfono de 9 dígitos...”)
if len(numero) != 9:
    raise FormatoDeNumeroNoValidoException

El ejemplo anterior también muestra cómo utilizar la sentencia raise para lanzar una excepción. En este caso, se podría suponer que la capa superior de código incluiría la lógica necesaria para capturar, y tratar, la excepción lanzada.

Para concluir esta sección, mencionaremos la cláusula finally. En esencia, si existe una cláusula finally, esta se ejecutará como última tarea antes de que finalice la sentencia try. La cláusula finally se ejecuta tanto si la sentencia try produce una excepción como si no. El siguiente ejemplo muestra un fragmento de código más completo.

def dividir(a, b):
    try:
        resultado = a / b
    except ZeroDivisionError:
        print(“División por cero.”)
    else:
        print(“El resultado es”, resultado)
    finally:
        print(“Ejecutando la cláusula finally”)