Manejo de Excepciones con try except en Python

PythonBeginner
Practicar Ahora

Introducción

En este laboratorio, aprenderá a manejar excepciones de manera efectiva en Python utilizando la sentencia try...except. Exploraremos cómo capturar excepciones específicas como ValueError, manejar múltiples tipos de excepciones y utilizar los bloques else y finally para tener un mayor control sobre el flujo de su programa. También aprenderá a lanzar excepciones personalizadas para señalar condiciones de error específicas en su código. A través de ejercicios prácticos, obtendrá experiencia práctica en la escritura de programas Python robustos y tolerantes a errores.

Este es un Guided Lab, que proporciona instrucciones paso a paso para ayudarte a aprender y practicar. Sigue las instrucciones cuidadosamente para completar cada paso y obtener experiencia práctica. Los datos históricos muestran que este es un laboratorio de nivel principiante con una tasa de finalización del 100%. Ha recibido una tasa de reseñas positivas del 100% por parte de los estudiantes.

Manejar ValueError con try except

En este paso, aprenderá a manejar un ValueError utilizando la sentencia try...except. Un ValueError ocurre cuando una función recibe un argumento del tipo correcto pero con un valor inapropiado. Un ejemplo común es intentar convertir una cadena que no es un número a un entero usando la función int().

Escribiremos un script de Python que solicita al usuario un número entero. Si la entrada no es un entero válido, capturaremos el ValueError y mostraremos un mensaje amigable para el usuario.

En el explorador de archivos del WebIDE a la izquierda, busque y abra el archivo handle_value_error.py ubicado en el directorio ~/project. Luego, agregue el siguiente código:

while True:
    try:
        x = int(input('Please enter an integer: '))
        print(f'You entered: {x}')
        break
    except ValueError:
        print('That was not a valid integer. Please try again.')

Guarde el archivo.

Ahora, abra la terminal integrada y ejecute el script usando el comando python:

python ~/project/handle_value_error.py

El script le pedirá que ingrese un número entero. Primero, intente ingresar un valor no entero como hello para ver el manejo de errores en acción. Luego, ingrese un entero válido como 123 para ver la ruta de ejecución exitosa.

Salida de ejemplo:

Please enter an integer: hello
That was not a valid integer. Please try again.
Please enter an integer: 123
You entered: 123

En este código:

  • El bucle while True: asegura que el programa siga pidiendo la entrada hasta que se ingrese un entero válido.
  • El bloque try contiene el código que podría generar una excepción, específicamente la llamada int(input(...)).
  • Si ocurre un ValueError en el bloque try, se ejecuta el código dentro del bloque except ValueError:.
  • Si no ocurre ninguna excepción, se ejecuta la sentencia print() y break sale del bucle.

Esto demuestra cómo try...except ValueError le permite manejar elegantemente entradas no válidas sin que el programa falle.

Manejar Múltiples Excepciones

Un bloque de código puede potencialmente generar diferentes tipos de excepciones. Python le permite manejar múltiples excepciones utilizando varias cláusulas except o agrupando las excepciones en una única cláusula except.

Escribamos un script que realice una división. Esta operación puede generar un ValueError si la entrada no es un número y un ZeroDivisionError si el divisor es cero.

En el WebIDE, abra el archivo ~/project/handle_multiple_exceptions.py y agregue el siguiente código. Esta versión utiliza bloques except separados para cada tipo de error.

try:
    numerator = int(input("Enter the numerator: "))
    denominator = int(input("Enter the denominator: "))
    result = numerator / denominator
    print(f"Result: {result}")
except ValueError:
    print("Invalid input. Please enter integers only.")
except ZeroDivisionError:
    print("Error: Division by zero is not allowed.")

Guarde el archivo y ejecútelo desde la terminal:

python ~/project/handle_multiple_exceptions.py

Pruebe el script con diferentes entradas para activar cada excepción:

  1. Ingrese un valor no entero (por ejemplo, abc).
  2. Ingrese 0 para el denominador.
  3. Ingrese enteros válidos para ambos.

Salida de ejemplo para división por cero:

Enter the numerator: 10
Enter the denominator: 0
Error: Division by zero is not allowed.

También puede manejar múltiples excepciones con una sola cláusula except agrupándolas en una tupla. Esto es útil para realizar la misma acción para diferentes errores.

Ahora, actualice el código en ~/project/handle_multiple_exceptions.py para usar este enfoque agrupado:

try:
    numerator = int(input("Enter the numerator: "))
    denominator = int(input("Enter the denominator: "))
    result = numerator / denominator
    print(f"Result: {result}")
except (ValueError, ZeroDivisionError):
    print("An error occurred: Invalid input or division by zero.")

Guarde el archivo y ejecútelo nuevamente con los mismos casos de prueba para observar el nuevo mensaje de error combinado.

Ejecutar Código con la Cláusula else

La sentencia try puede incluir una cláusula else opcional. El código en el bloque else se ejecuta solo si el bloque try se completa sin generar ninguna excepción. Esto es útil para separar el código que debe ejecutarse en caso de éxito del bloque try principal.

Modifiquemos nuestro script de división para incluir un bloque else.

En el WebIDE, abra el archivo ~/project/try_except_else.py y agregue el siguiente código:

try:
    numerator = int(input("Enter the numerator: "))
    denominator = int(input("Enter the denominator: "))
    result = numerator / denominator
except (ValueError, ZeroDivisionError):
    print("An error occurred: Invalid input or division by zero.")
else:
    print("Division successful!")
    print(f"Result: {result}")

Guarde el archivo y ejecútelo desde la terminal:

python ~/project/try_except_else.py

Pruebe el script con entradas que causan fallos y con entradas exitosas:

  1. Ingrese 0 para el denominador para activar una excepción.
  2. Ingrese enteros válidos y distintos de cero para ejecutar el bloque else.

Salidas de ejemplo:

Enter the numerator: 10
Enter the denominator: 0
An error occurred: Invalid input or division by zero.
Enter the numerator: 10
Enter the denominator: 2
Division successful!
Result: 5.0

Como puede ver, los mensajes en el bloque else solo se imprimen cuando la división es exitosa. Si ocurre una excepción, se ejecuta el bloque except y se omite el bloque else.

Asegurar la Ejecución del Código con la Cláusula finally

La sentencia try también tiene una cláusula finally opcional. El código dentro del bloque finally se ejecuta siempre, independientemente de si ocurrió o no una excepción en el bloque try. Esto lo hace ideal para acciones de limpieza, como cerrar archivos o liberar recursos, que deben realizarse en todos los escenarios.

Agreguemos un bloque finally a nuestro ejemplo de división.

En el WebIDE, abra el archivo ~/project/try_except_finally.py y agregue el siguiente código:

try:
    numerator = int(input("Enter the numerator: "))
    denominator = int(input("Enter the denominator: "))
    result = numerator / denominator
    print(f"Result: {result}")
except (ValueError, ZeroDivisionError):
    print("An error occurred: Invalid input or division by zero.")
finally:
    print("Execution finished.")

Guarde el archivo y ejecútelo desde la terminal:

python ~/project/try_except_finally.py

Ejecute el script con entradas que causan fallos y con entradas exitosas:

  1. Ingrese 0 para el denominador para activar una excepción.
  2. Ingrese enteros válidos y distintos de cero.

Salidas de ejemplo:

Enter the numerator: 10
Enter the denominator: 0
An error occurred: Invalid input or division by zero.
Execution finished.
Enter the numerator: 10
Enter the denominator: 2
Result: 5.0
Execution finished.

Observe que el mensaje "Execution finished." del bloque finally se imprime en ambos casos. Se garantiza que el bloque finally se ejecutará, lo que lo convierte en un lugar confiable para el código de limpieza esencial.

Generar Excepciones Personalizadas

A veces necesita señalar una condición de error que no es una excepción incorporada de Python. Puede hacerlo con la sentencia raise, que le permite crear y activar sus propias excepciones. Esto es útil para hacer que el manejo de errores de su aplicación sea más específico y descriptivo.

Primero, veamos cómo usar raise con una excepción incorporada. En el WebIDE, abra el archivo ~/project/raise_exception.py y agregue el siguiente código:

def check_positive(number):
    if number <= 0:
        raise ValueError("Input must be a positive number")
    print(f"The number {number} is positive.")

try:
    check_positive(-5)
except ValueError as e:
    print(f"Caught an exception: {e}")

try:
    check_positive(10)
except ValueError as e:
    print(f"Caught an exception: {e}")

Guarde el archivo y ejecútelo desde la terminal:

python ~/project/raise_exception.py

La salida será:

Caught an exception: Input must be a positive number
The number 10 is positive.

Aquí, la función check_positive genera una ValueError si la entrada no es positiva, la cual es capturada por el bloque except.

Ahora, definamos y generemos una excepción personalizada. Las excepciones personalizadas son clases que heredan de la clase incorporada Exception.

En el WebIDE, abra el archivo ~/project/custom_exception.py y agregue el siguiente código:

class NegativeNumberError(Exception):
    """Custom exception raised for negative numbers."""
    pass

def process_positive_number(number):
    if number < 0:
        raise NegativeNumberError("Negative numbers are not allowed")
    print(f"Processing positive number: {number}")

try:
    process_positive_number(-10)
except NegativeNumberError as e:
    print(f"Caught custom exception: {e}")

try:
    process_positive_number(20)
except NegativeNumberError as e:
    print(f"Caught custom exception: {e}")

Guarde el archivo y ejecútelo desde la terminal:

python ~/project/custom_exception.py

La salida será:

Caught custom exception: Negative numbers are not allowed
Processing positive number: 20

En este ejemplo, definimos nuestra propia NegativeNumberError y la generamos bajo una condición específica. Luego, el bloque try...except captura específicamente este tipo de error personalizado, haciendo el manejo de errores más preciso.

Resumen

En este laboratorio, aprendió a implementar un manejo de errores robusto en Python. Comenzó utilizando un bloque try...except para capturar un ValueError específico proveniente de la entrada del usuario. Luego amplió esto manejando múltiples tipos de excepciones, tanto por separado como en un único bloque. También aprendió a usar la cláusula else para ejecutar código solo cuando no ocurren excepciones y la cláusula finally para ejecutar código de limpieza en todas las situaciones. Finalmente, practicó la creación y generación de excepciones personalizadas para manejar errores específicos de la aplicación, haciendo su código más legible y mantenible.