Saltar al contenido
Portada » Lenguajes » 6. Manejo de Errores y Excepciones en Python

6. Manejo de Errores y Excepciones en Python

Manejo de Errores y Excepciones en Python. En este breve capítulo, pero no por ello menos importante, abordaremos un aspecto fundamental de la programación: el manejo de errores y excepciones. Los errores son inevitables en cualquier código y aprender a anticiparlos y gestionarlos correctamente es esencial. Python ofrece herramientas específicas, como las instrucciones try, except, finally y else, que nos permiten capturar y manejar estos errores sin interrumpir el flujo normal de ejecución.

Un buen manejo de errores y excepciones es crucial para escribir programas robustos y fiables. Los errores pueden ocurrir por muchas razones, como entradas incorrectas, problemas con archivos, conexiones de red fallidas, etc. El manejo de excepciones permite a los programadores interceptar estos errores, prevenir que el programa se cierre de manera abrupta y proporcionar un control sobre lo que ocurre en situaciones inesperadas.

Veremos cómo capturar excepciones de forma específica y cómo usar bloques de código para asegurarnos de que ciertas tareas se completen, incluso si ocurre un error. También exploraremos cómo definir nuestras propias excepciones personalizadas, adaptadas a las necesidades de nuestro programa. ¡Empecemos!

Uso de try y except

La estructura básica para el manejo de excepciones en Python se realiza mediante los bloques try y except. El código que puede generar una excepción se coloca dentro del bloque try, y las excepciones que se quieran capturar se gestionan en el bloque except.

Sintaxis básica:
try:
    # Código que puede generar una excepción
except:
    # Código que se ejecuta si ocurre una excepción

Ejemplo:

try:
    x = 10 / 0  # Esto generará un error de división por cero
except:
    print("Ocurrió un error.")

En este ejemplo, el programa no se detiene por el error, sino que captura la excepción y muestra el mensaje de que ocurrió un error.

Captura de excepciones específicas

Puedes capturar tipos específicos de excepciones en Python, lo que es útil para manejar diferentes errores de manera más precisa. Algunas excepciones comunes son:

  • ZeroDivisionError: División por cero.
  • ValueError: Operaciones inválidas con tipos de datos (por ejemplo, convertir una cadena no numérica en entero).
  • FileNotFoundError: Intento de abrir un archivo que no existe.
Ejemplo de captura de excepciones específicas:
try:
    x = int("Hola")  # Esto generará un ValueError
except ValueError:
    print("Hubo un problema al convertir la cadena en número.")

En este caso se ha forzado un error del tipo ValueError pues Hola no es un número, por tanto se captura la excepción y se maneja mostrando el mensaje de error.

Múltiples excepciones:

Puedes manejar múltiples tipos de excepciones de manera separada.

try:
    x = 10 / 0  # Generará un ZeroDivisionError
except ZeroDivisionError:
    print("No se puede dividir entre cero.")
except ValueError:
    print("Valor incorrecto.")

Uso de else y finally

Python también permite añadir bloques else y finally a la estructura de manejo de excepciones.

else:

El bloque else se ejecuta solo si no ocurre ninguna excepción en el bloque try. Esto permite separar el código que se ejecuta en caso de éxito del código que maneja los errores.

Ejemplo:
try:
    x = 10 / 2  # No generará un error
except ZeroDivisionError:
    print("Error: división por cero.")
else:
    print("La operación fue exitosa.")

En este caso, como no hay error, se ejecuta el bloque else y se imprimirá que la operación ha sido exitosa.

finally:

El bloque finally se ejecuta siempre, independientemente de si ocurre una excepción o no. Es útil para realizar tareas de limpieza, como cerrar archivos o liberar recursos.

Ejemplo:
try:
    archivo = open("mi_archivo.txt", "r")
except FileNotFoundError:
    print("El archivo no se encontró.")
finally:
    print("Este mensaje se muestra siempre.")

En este caso, en el caso de que el archivo no se encuentre mostrará el mensaje de «El archivo no se encontró» y además el mensaje de «Este mensaje se muestra siempre«. Si el archivo existe, mostrará únicamente el mensaje del bloque finally «Este mensaje se muestra siempre«.

Creación de excepciones personalizadas

Python permite crear excepciones personalizadas para manejar situaciones específicas en un programa. Esto se hace mediante la creación de nuevas clases que heredan de la clase base Exception.

Ejemplo:
class ErrorPersonalizado(Exception):
    pass

def verificar_valor(valor):
    if valor < 0:
        raise ErrorPersonalizado("El valor no puede ser negativo.")
    return valor

try:
    verificar_valor(-10)
except ErrorPersonalizado as e:
    print(f"Ocurrió un error: {e}")

En este ejemplo se crea una excepción personalizada ErrorPersonalizado y si se pasa un valor negativo a la función verificar_valor(), la excepción es lanzada con un mensaje personalizado.

Uso de raise:

La palabra clave raise se utiliza para lanzar excepciones explícitamente.

def dividir(a, b):
    if b == 0:
        raise ZeroDivisionError("No se puede dividir entre cero.")
    return a / b

try:
    dividir(10, 0)
except ZeroDivisionError as e:
    print(e)

En este caso raise se utiliza para lanzar manualmente un ZeroDivisionError con un mensaje personalizado.

A continuación te muestro una tabla con los errores más comunes que puedes encontrar y manejar.

ExcepciónDescripción
ArithmeticErrorError base para excepciones aritméticas, como OverflowError, ZeroDivisionError y FloatingPointError.
ZeroDivisionErrorSe produce cuando se intenta dividir un número por cero.
ValueErrorSe lanza cuando una operación o función recibe un argumento de tipo correcto, pero con un valor inapropiado (ej., convertir “abc” a entero).
TypeErrorOcurre cuando se intenta realizar una operación con tipos de datos incompatibles, como sumar una cadena con un entero.
FileNotFoundErrorSurge cuando se intenta abrir o manipular un archivo que no existe.
IndexErrorSe lanza al intentar acceder a un índice de una secuencia (como una lista o cadena) que está fuera del rango de la misma.
KeyErrorOcurre cuando se intenta acceder a una clave que no existe en un diccionario.
AttributeErrorSe produce al intentar acceder a un atributo o método que un objeto no tiene.
NameErrorSe lanza cuando una variable o nombre de función no está definido en el ámbito actual.
IndentationErrorError de sintaxis que ocurre cuando la indentación en el código no es correcta.
SyntaxErrorSe produce cuando el intérprete de Python encuentra un error en la sintaxis del código.
RuntimeErrorExcepción general que ocurre en tiempo de ejecución cuando no se especifica otra excepción más adecuada.
ImportErrorSe lanza cuando no se puede importar un módulo o encontrar una función/clase en un módulo.
ModuleNotFoundErrorExcepción específica de ImportError que ocurre cuando el módulo no se encuentra en el entorno.
StopIterationSe lanza para indicar el final de una iteración cuando se utiliza next() en un iterador y no quedan elementos.
OverflowErrorOcurre cuando el resultado de una operación aritmética es demasiado grande para ser representado.
MemoryErrorSe lanza cuando el programa se queda sin memoria para almacenar más datos u objetos.
FloatingPointErrorError relacionado con operaciones en punto flotante (números decimales), aunque es raro ya que las operaciones suelen manejarlo internamente.
EOFErrorSe produce cuando se alcanza el final de un archivo o entrada de datos antes de completar la operación esperada.
OSErrorClase base para errores del sistema operativo, como FileNotFoundError, PermissionError, entre otros.
PermissionErrorEs un subtipo de OSError, se lanza cuando el usuario no tiene permisos suficientes para realizar una operación en el sistema de archivos.
UnboundLocalErrorOcurre cuando se intenta utilizar una variable local antes de que se le asigne un valor en una función.
AssertionErrorSe lanza cuando una declaración assert en el código es falsa.
TimeoutErrorOcurre cuando una operación alcanza el límite de tiempo sin completarse.
NotImplementedErrorIndica que una funcionalidad en una clase o función no está implementada.
IsADirectoryErrorSe produce cuando se intenta realizar una operación de archivo en un directorio (por ejemplo, abrir un directorio como si fuera un archivo).
NotADirectoryErrorSe lanza cuando se intenta acceder a un archivo como si fuera un directorio.
BrokenPipeErrorSe produce cuando se intenta escribir en una conexión cerrada o canal (pipe).
ConnectionErrorClase base para errores relacionados con la conexión, como ConnectionAbortedError, ConnectionRefusedError, etc.
ConnectionRefusedErrorSe produce cuando se intenta conectar a un servidor que ha rechazado la conexión.
ConnectionAbortedErrorOcurre cuando una conexión se interrumpe abruptamente por el servidor.

Resumen

El manejo de excepciones es una técnica esencial en Python que permite crear programas más estables y seguros. Los bloques try, except, else y finally ofrecen flexibilidad en el manejo de errores, mientras que la capacidad de crear excepciones personalizadas permite capturar y manejar errores específicos de cada aplicación. Con una gestión adecuada de errores los programas pueden ofrecer una mejor experiencia al usuario, proporcionando mensajes claros y evitando fallos inesperados.

Ejercicio 1: Dividir dos números

Escribe una función llamada division que reciba dos números y devuelva el resultado de la división del primero entre el segundo. Si el segundo número es cero, la función debe manejar la excepción e imprimir un mensaje de error en lugar de detener el programa.
# Definimos la función division que recibe dos parámetros numéricos
def division(a, b):
    try:
        resultado = a / b  # Intentamos dividir a entre b
        return resultado
    except ZeroDivisionError:  # Capturamos la excepción si b es cero
        print("Error: No se puede dividir entre cero.")

# Probamos la función con diferentes valores
print(division(10, 2))  # Salida: 5.0
print(division(10, 0))  # Salida: "Error: No se puede dividir entre cero."

Explicación:
La función intenta dividir a entre b. Si b es cero, se produce una excepción ZeroDivisionError, que capturamos con except para evitar que el programa se detenga. En su lugar, mostramos un mensaje indicando que no es posible realizar la operación.

Ejercicio 2: Conversión de cadena a número

Crea una función llamada convertir_a_entero que reciba una cadena de texto y la convierta en un número entero. Si la conversión no es posible, la función debe manejar el error e imprimir un mensaje que indique que el valor ingresado no es un número válido.
# Definimos la función convertir_a_entero que recibe una cadena de texto
def convertir_a_entero(cadena):
    try:
        numero = int(cadena)  # Intentamos convertir la cadena a entero
        return numero
    except ValueError:  # Capturamos la excepción si la cadena no es un número válido
        print("Error: El valor ingresado no es un número válido.")

# Probamos la función con diferentes cadenas
print(convertir_a_entero("42"))    # Salida: 42
print(convertir_a_entero("hola"))  # Salida: "Error: El valor ingresado no es un número válido."

Explicación:
La función intenta convertir la cadena cadena en un entero usando int(). Si el valor no puede convertirse, se lanza una excepción ValueError, que capturamos para mostrar un mensaje de error sin interrumpir el programa.

Ejercicio 3: Manejo de múltiples excepciones

Escribe una función llamada operacion_aritmetica que reciba dos números y realice una división. La función debe manejar tanto ZeroDivisionError (si el segundo número es cero) como TypeError (si alguno de los argumentos no es un número). En ambos casos, la función debe imprimir un mensaje adecuado.
# Definimos la función operacion_aritmetica que recibe dos parámetros
def operacion_aritmetica(a, b):
    try:
        resultado = a / b  # Intentamos realizar la división
        return resultado
    except ZeroDivisionError:
        print("Error: No se puede dividir entre cero.")
    except TypeError:
        print("Error: Ambos parámetros deben ser números.")

# Probamos la función con diferentes entradas
print(operacion_aritmetica(10, 2))       # Salida: 5.0
print(operacion_aritmetica(10, 0))       # Salida: "Error: No se puede dividir entre cero."
print(operacion_aritmetica(10, "dos"))   # Salida: "Error: Ambos parámetros deben ser números."

Explicación:
La función intenta dividir a entre b y maneja dos posibles errores: ZeroDivisionError (si intentamos dividir entre cero) y TypeError (si los parámetros no son números). Cada excepción tiene un mensaje específico para informar sobre el tipo de error.

Ejercicio 4: Leer un archivo

Crea una función llamada leer_archivo que reciba un nombre de archivo como parámetro e intente abrirlo y leer su contenido. Si el archivo no existe, la función debe manejar la excepción y mostrar un mensaje de error. Utiliza finally para cerrar el archivo solo si ha sido abierto correctamente.
# Definimos la función leer_archivo que recibe el nombre de un archivo como parámetro
def leer_archivo(nombre_archivo):
    try:
        archivo = open(nombre_archivo, 'r')  # Intentamos abrir el archivo en modo lectura
        contenido = archivo.read()  # Leemos el contenido del archivo
        return contenido
    except FileNotFoundError:  # Capturamos la excepción si el archivo no existe
        print("Error: El archivo no se encuentra.")
    finally:
        try:
            archivo.close()  # Intentamos cerrar el archivo si ha sido abierto
        except NameError:
            pass  # Si archivo no fue definido, no hay necesidad de cerrarlo

# Probamos la función con un archivo inexistente
print(leer_archivo("archivo_inexistente.txt"))

Explicación:
La función intenta abrir y leer un archivo. Si el archivo no existe, se lanza una excepción FileNotFoundError, que capturamos para mostrar un mensaje. El bloque finally se asegura de cerrar el archivo si fue abierto; si no fue abierto (como en caso de error), NameError evita cerrar un archivo inexistente.

Ejercicio 5: Crear una excepción personalizada

Define una excepción personalizada llamada ErrorDeNegativo y crea una función llamada calcular_raiz que reciba un número. Si el número es negativo, lanza ErrorDeNegativo con un mensaje adecuado. Si es positivo, devuelve su raíz cuadrada.
# Definimos la excepción personalizada
class ErrorDeNegativo(Exception):
    pass  # Usamos pass porque la excepción solo necesita un nombre

# Definimos la función calcular_raiz que recibe un número
import math

def calcular_raiz(numero):
    if numero < 0:
        raise ErrorDeNegativo("Error: No se puede calcular la raíz cuadrada de un número negativo.")
    return math.sqrt(numero)  # Calculamos la raíz cuadrada para números no negativos

# Probamos la función
try:
    print(calcular_raiz(25))   # Salida: 5.0
    print(calcular_raiz(-10))  # Lanza ErrorDeNegativo
except ErrorDeNegativo as e:
    print(e)  # Salida: "Error: No se puede calcular la raíz cuadrada de un número negativo."

Explicación:
Creamos una excepción personalizada ErrorDeNegativo para detectar valores negativos en la función calcular_raiz. La función lanza ErrorDeNegativo si el número es negativo, y al capturarla, mostramos el mensaje adecuado.

Bibliografía de Python de interés.

Logo Python. Manejor de Errores y Excepciones en Python

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *