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
.
@Nota: En este punto hacemos uso de la Programación Orientada a Objetos con la creación de una clase. Esta técnica de programación no la hemos visto todavía, lo veremos en el siguiente capítulo, pero no te preocupes porque vas a entender el código fácilmente.
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ón | Descripción |
---|---|
ArithmeticError | Error base para excepciones aritméticas, como OverflowError , ZeroDivisionError y FloatingPointError . |
ZeroDivisionError | Se produce cuando se intenta dividir un número por cero. |
ValueError | Se lanza cuando una operación o función recibe un argumento de tipo correcto, pero con un valor inapropiado (ej., convertir “abc” a entero). |
TypeError | Ocurre cuando se intenta realizar una operación con tipos de datos incompatibles, como sumar una cadena con un entero. |
FileNotFoundError | Surge cuando se intenta abrir o manipular un archivo que no existe. |
IndexError | Se lanza al intentar acceder a un índice de una secuencia (como una lista o cadena) que está fuera del rango de la misma. |
KeyError | Ocurre cuando se intenta acceder a una clave que no existe en un diccionario. |
AttributeError | Se produce al intentar acceder a un atributo o método que un objeto no tiene. |
NameError | Se lanza cuando una variable o nombre de función no está definido en el ámbito actual. |
IndentationError | Error de sintaxis que ocurre cuando la indentación en el código no es correcta. |
SyntaxError | Se produce cuando el intérprete de Python encuentra un error en la sintaxis del código. |
RuntimeError | Excepción general que ocurre en tiempo de ejecución cuando no se especifica otra excepción más adecuada. |
ImportError | Se lanza cuando no se puede importar un módulo o encontrar una función/clase en un módulo. |
ModuleNotFoundError | Excepción específica de ImportError que ocurre cuando el módulo no se encuentra en el entorno. |
StopIteration | Se lanza para indicar el final de una iteración cuando se utiliza next() en un iterador y no quedan elementos. |
OverflowError | Ocurre cuando el resultado de una operación aritmética es demasiado grande para ser representado. |
MemoryError | Se lanza cuando el programa se queda sin memoria para almacenar más datos u objetos. |
FloatingPointError | Error relacionado con operaciones en punto flotante (números decimales), aunque es raro ya que las operaciones suelen manejarlo internamente. |
EOFError | Se produce cuando se alcanza el final de un archivo o entrada de datos antes de completar la operación esperada. |
OSError | Clase base para errores del sistema operativo, como FileNotFoundError , PermissionError , entre otros. |
PermissionError | Es un subtipo de OSError , se lanza cuando el usuario no tiene permisos suficientes para realizar una operación en el sistema de archivos. |
UnboundLocalError | Ocurre cuando se intenta utilizar una variable local antes de que se le asigne un valor en una función. |
AssertionError | Se lanza cuando una declaración assert en el código es falsa. |
TimeoutError | Ocurre cuando una operación alcanza el límite de tiempo sin completarse. |
NotImplementedError | Indica que una funcionalidad en una clase o función no está implementada. |
IsADirectoryError | Se produce cuando se intenta realizar una operación de archivo en un directorio (por ejemplo, abrir un directorio como si fuera un archivo). |
NotADirectoryError | Se lanza cuando se intenta acceder a un archivo como si fuera un directorio. |
BrokenPipeError | Se produce cuando se intenta escribir en una conexión cerrada o canal (pipe). |
ConnectionError | Clase base para errores relacionados con la conexión, como ConnectionAbortedError , ConnectionRefusedError , etc. |
ConnectionRefusedError | Se produce cuando se intenta conectar a un servidor que ha rechazado la conexión. |
ConnectionAbortedError | Ocurre 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.
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.
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.
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.
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.
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.
- Curso de Programación Python. Autor: Arturo Montejo Ráez y Salud María Jiménez Zafra (Editorial Anaya)
- Aprende Python desde cero hasta avanzado. Autor: Xavier Reyes Ochoa (Editorial Book Shelter GmbH)
- Aprende la Programación Orientada a Objetos con el lenguaje Python. Autor: Vincent Boucheny (Editorial Ediciones ENI)
- 100 Ejercicios Python para praticar. Autor: Laurentine K.Masson (Editorial: Publicación Independiente).