curso
Manejo de Excepciones y Errores en Python
Los errores y las excepciones pueden provocar un comportamiento inesperado o incluso detener la ejecución de un programa. Python proporciona varias funciones y mecanismos para tratar estos problemas y mejorar la solidez del código. En este tutorial, aprenderemos varios tipos de error y funciones incorporadas con ejemplos.
Un error es un problema en un programa que impide que éste complete su tarea. En comparación, una excepción es una condición que interrumpe el flujo normal del programa. Tanto los errores como las excepciones son un tipo de error en tiempo de ejecución, lo que significa que se producen durante la ejecución de un programa.
En palabras sencillas, el error es un problema crítico que una aplicación normal no debe captar, mientras que una excepción es una condición que un programa debe captar.
Vamos a aprender más sobre errores y excepciones viendo varios ejemplos. Para ejecutarlos fácilmente, puedes crear gratuitamente un libro de trabajo DataLab que tenga Python preinstalado y contenga todos los ejemplos de código.
Errores en Python
Aquí tienes un ejemplo de error sintáctico en el que un retorno fuera de la función no significa nada. No debemos tratar los errores en un programa. En su lugar, debemos crear una función que devuelva la cadena.
return "DataCamp"
Input In [1]
return "DataCamp"
^
SyntaxError: 'return' outside function
Hemos creado la función pero con una sangría incorrecta. No debemos tratar los errores de sangría en tiempo de ejecución. Podemos hacerlo manualmente o utilizar herramientas de formateo de código.
def fun():
return "DataCamp"
Input In [2]
return "DataCamp"
^
IndentationError: expected an indented block
Excepciones en Python
Hemos encontrado un ZeroDivisionError
(Excepción). Podemos manejarlo en tiempo de ejecución utilizando los bloques try
y except
.
test = 1/0
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
Input In [4], in <cell line: 1>()
----> 1 test = 1/0
ZeroDivisionError: division by zero
NameError
Las excepciones son bastante frecuentes cuando no se encuentra una variable. También podemos tratar la excepción sustituyendo la variable o imprimiendo la advertencia.
y = test
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Input In [5], in <cell line: 1>()
----> 1 y = test
NameError
Excepciones incorporadas en Python
Aquí tienes la lista de excepciones por defecto de Python con sus descripciones:
AssertionError
: cuando falla la sentencia assert.EOFError
: se activa cuando la funcióninput()
cumple la condición de fin de archivo.AttributeError
: se produce cuando falla la asignación o la referencia del atributo.TabError
: se plantea cuando las sangrías consisten en tabulaciones o espacios incoherentes.ImportError
: se produce cuando falla la importación del módulo.IndexError
: se produce cuando el índice de una secuencia está fuera de rangoKeyboardInterrupt
: se activa cuando el usuario introduce teclas de interrupción (Ctrl + C o Supr).RuntimeError
: se produce cuando un error no entra en ninguna categoría.NameError
: aparece cuando no se encuentra una variable en el ámbito local o global.MemoryError
: se activa cuando los programas se quedan sin memoria.ValueError
: se produce cuando la operación o función recibe un argumento con el tipo correcto pero el valor incorrecto.ZeroDivisionError
: que aparece cuando divides un valor o una variable por cero.SyntaxError
: planteado por el analizador sintáctico cuando la sintaxis de Python es incorrecta.IndentationError
: se produce cuando hay una sangría incorrecta.SystemError
: se produce cuando el intérprete detecta un error interno.
Puedes encontrar una lista completa de errores y excepciones en Python leyendo la documentación.
Aprende sobre las excepciones en Python siguiendo nuestro curso de Programación Orientada a Objetos en Python. Te enseñará a crear clases y a aprovechar la herencia y el polimorfismo para reutilizar y optimizar el código.
Manejo de excepciones con try, except, else y finally
Después de conocer los errores y las excepciones, aprenderemos a manejarlos utilizando los bloques try
, except
, else
, y finally
.
Entonces, ¿qué queremos decir con manejarlos? En circunstancias normales, estos errores detendrán la ejecución del código y mostrarán el mensaje de error. Para crear sistemas estables, tenemos que anticiparnos a estos errores e idear soluciones alternativas o mensajes de advertencia.
En esta sección, aprenderemos qué hace cada bloque y cómo podemos utilizarlos para escribir código robusto.
La sentencia try y except
La forma más sencilla de manejar excepciones en Python es utilizando el bloque try
y except
.
- Ejecuta el código bajo la declaración
try
. - Cuando se produzca una excepción, ejecuta el código bajo la sentencia
except
.
En lugar de detenernos ante un error o una excepción, nuestro código avanzará hacia soluciones alternativas.
Ejemplo sencillo
En el primer ejemplo, intentaremos imprimir la variable indefinida x
. En circunstancias normales, debería lanzar el error y detener la ejecución, pero con el bloque try
y except
, podemos cambiar el comportamiento del flujo.
- El programa ejecutará el código bajo la sentencia
try
. - Como sabemos, ese
x
no está definido, por lo que ejecutará la sentencia except e imprimirá la advertencia.
try:
print(x)
except:
print("An exception has occurred!")
An exception has occurred!
Ejemplo de sentencia except múltiple
En el segundo ejemplo, utilizaremos varias sentencias except
para gestionar varios tipos de excepciones.
- Si se produce una excepción
ZeroDivisionError
, el programa imprimirá "No se puede dividir un valor por cero". - El resto de las excepciones imprimirán "Algo más salió mal".
Nos permite escribir código flexible que puede manejar varias excepciones a la vez sin romperse.
try:
print(1/0)
except ZeroDivisionError:
print("You cannot divide a value with zero")
except:
print("Something else went wrong")
You cannot divide a value with zero
Cargar el archivo de ejemplo
Veamos ahora un ejemplo más práctico.
En el código siguiente, estamos leyendo el archivo CSV, y cuando se produzca la excepción FileNotFoundError
, el código imprimirá el error y un mensaje adicional sobre el archivo data.csv
.
Sí, podemos imprimir mensajes de error predeterminados sin interrumpir la ejecución.
try:
with open('data.csv') as file:
read_data = file.read()
except FileNotFoundError as fnf_error:
print(fnf_error)
print("Explanation: We cannot load the 'data.csv' file")
[Errno 2] No such file or directory: 'data.csv'
Explanation: We cannot load the 'data.csv' file
La cláusula try con else
Hemos aprendido sobre try
y except
, y ahora aprenderemos sobre la declaración else
.
Cuando la sentencia try
no lanza una excepción, el código entra en el bloque else
. Es el remedio o una opción alternativa cuando esperas que una parte de tu script produzca una excepción. Generalmente se utiliza en una breve sección de configuración o verificación en la que no quieres que se oculten ciertos errores.
Nota: En el bloque try-except, puedes utilizar else
después de todas las sentencias except
.
Ejemplo sencillo
Estamos añadiendo la declaración else
al ejemplo ZeroDivisionError
. Como podemos ver, cuando no hay excepciones, se ejecuta la función de impresión bajo la sentencia else
, mostrando el resultado.
try:
result = 1/3
except ZeroDivisionError as err:
print(err)
else:
print(f"Your answer is {result}")
Your answer is 0.3333333333333333
Ejemplo de IndexError con else
Vamos a aprender más creando una función sencilla y probándola en varios escenarios.
La función find_nth_value()
tiene como argumentos x
(lista) y n
(número de índice). Hemos creado un bloque try
, except
, y else
para gestionar la excepción IndexError
.
x = [5,8,9,13]
def find_nth_value(x,n):
try:
result = x[n]
except IndexError as err:
print(err)
else:
print("Your answer is ", result)
La lista x
tiene cuatro valores, y los probaremos para los índices 6º y 2º.
# Testing
find_nth_value(x,6)
find_nth_value(x,2)
- En n=6, se lanzó la excepción
IndexError
, y llegamos a ver el mensaje de error por defecto "índice de lista fuera de rango". - En n=2, no se produjo ninguna excepción, y la función imprimió el resultado que está debajo de la declaración
else
.
list index out of range
Your answer is 9
La palabra clave finally en Python
La palabra clave finally
del bloque try
-except
se ejecuta siempre, independientemente de si hay una excepción o no. En palabras sencillas, el bloque de código finally
se ejecuta después de que el bloque try
, except
y else
hayan finalizado. Es muy útil para limpiar los recursos y cerrar el objeto, sobre todo para cerrar los archivos.
La función divide
se crea para gestionar las excepciones de ZeroDivisionError
y mostrar el resultado cuando no hay excepciones. Sea cual sea el resultado, siempre se ejecutará finally
para imprimir "Code by DataCamp" en color verde.
def divide(x,y):
try:
result = x/y
except ZeroDivisionError:
print("Please change 'y' argument to non-zero value")
except:
print("Something went wrong")
else:
print(f"Your answer is {result}")
finally:
print("\033[92m Code by DataCamp\033[00m")
En la primera prueba, estamos dividiendo 1 entre 0, lo que debería lanzar la excepción ZeroDivisionError
e imprimir el mensaje. Como podemos ver, tenemos una línea adicional después del mensaje de error.
divide(1,0)
Please change 'y' argument to non-zero value
Code by DataCamp
Cuando añadimos una entrada válida, muestra el resultado ejecutando else
y finally
bloqueando.
divide(3,4)
Your answer is 0.75
Code by DataCamp
En lugar de un número entero, hemos añadido una cadena como segundo argumento, lo que ha provocado una excepción, que es distinta de ZeroDivisionError
, con un mensaje diferente.
divide(1,'g')
Something went wrong
Code by DataCamp
En los tres supuestos, hay una cosa en común. El código siempre ejecuta la función de impresión bajo la sentencia finally
.
Si eres nuevo en Python y quieres programar como un auténtico programador, prueba nuestro curso de Programación en Python. Aprenderás a escribir código eficiente, funciones de Python, ingeniería de software, pruebas unitarias y programación orientada a objetos.
Manejo de excepciones anidadas en Python
Necesitamos el manejo de excepciones anidadas cuando preparamos el programa para manejar varias excepciones en una secuencia. Por ejemplo, podemos añadir otro bloque try-except bajo la sentencia else
. Por tanto, si la primera declaración no provoca una excepción, comprueba la segunda declaración con la otra mitad del código.
Modificar la función dividir
Hemos modificado la función divide
del ejemplo anterior y hemos añadido un bloque try-except anidado bajo la sentencia else
. Así, si no hay AttributeError
, ejecutará el else
y comprobará el nuevo código para la excepción ZeroDivisionError
.
def divide(x,y):
try:
value = 50
x.append(value)
except AttributeError as atr_err:
print(atr_err)
else:
try:
result = [i / y for i in x]
print( result )
except ZeroDivisionError:
print("Please change 'y' argument to non-zero value")
finally:
print("\033[92m Code by DataCamp\033[00m")
En el primer supuesto, proporcionamos la lista de cuatro valores x
y el denominador 3. El script añadirá 50 a la lista, dividirá el valor individual de la lista por 3 y mostrará el resultado.
x = [40,65,70,87]
divide(x,3)
La función se ha ejecutado correctamente sin lanzar ninguna excepción.
[13.333333333333334, 21.666666666666668, 23.333333333333332, 29.0, 16.666666666666668]
Code by DataCamp
En lugar de una lista, hemos proporcionado un número entero al primer argumento, que ha planteado AttributeError
.
divide(4,3)
'int' object has no attribute 'append'
Code by DataCamp
En el último escenario, hemos proporcionado la lista, pero 0 es el segundo argumento que ha planteado la excepción ZeroDivisionError
en la declaración else
.
divide(x,0)
Please change 'y' argument to non-zero value
Code by DataCamp
Ejemplo de edición de archivos
Veamos ejemplos más prácticos de carga del archivo, escritura de un texto y cierre del archivo.
La función file_editor()
- Comprueba la excepción
FileNotFoundError
para la funciónopen()
. - Si no se lanza la excepción externa, buscará la excepción de la función
write()
. - Pase lo que pase, después de abrir el archivo, lo cerrará ejecutando la sentencia
finally
. - Si la sentencia try externa lanza la excepción, devolverá el mensaje de error con una ruta de archivo no válida.
def file_editor(path,text):
try:
data = open(path)
try:
data.write(text)
except:
print("Unable to write the data. Please add an append: 'a' or write: 'w' parameter to the open() function.")
finally:
data.close()
except:
print(f"{path} file is not found!!")
En el primer caso, proporcionamos la ruta del archivo y el texto.
path = "data.txt"
text = "DataLab: Share your data analysis in a cloud-based environment--no installation required."
file_editor(path,text)
Se lanza la excepción externa.
data.txt file is not found!!
Para resolver la excepción de archivo no encontrado, debemos crear un archivo data.txt
utilizando el comando de Linux echo
.
!echo "File by DataCamp" > "data.txt"
Después, vuelve a ejecutar la función file_editor()
.
file_editor(path,text)
Se lanza la excepción interna, ya que la función write()
no es capaz de añadir el texto.
Unable to write the data. Please add an append: 'a' or write: 'w' parameter to the open() function.
Para resolver este problema, tenemos que cambiar la tercera línea de data = open(path)
a data = open(path, 'a')
. Nos permitirá añadir el nuevo texto al archivo.
Tras volver a ejecutar la función, hemos añadido correctamente el texto al archivo.
file_editor(path,text)
No se recomienda el manejo anidado de excepciones, ya que lo hace más complejo; los desarrolladores utilizan varios bloques try
-except
para crear un manejo de excepciones secuencial y sencillo.
Nota: también puedes añadir un bloque anidado try
-except
bajo la declaración try
o except
. Sólo depende de tus necesidades.
Lanzar excepciones en Python
Como desarrollador de Python, puedes lanzar una excepción si se cumplen determinadas condiciones. Te permite interrumpir el programa en función de tus necesidades.
Para lanzar una excepción, tenemos que utilizar la palabra clave raise
seguida de un nombre de excepción.
Ejemplo de error de valor
Podemos simplemente lanzar excepciones añadiendo una palabra clave raise en la declaración if
/else
.
En el ejemplo, subimos el ValueError
si el valor supera 1.000. Hemos cambiado el valor a 2.000, lo que ha hecho que la declaración if
TRUE
y ha planteado ValueError
con el mensaje personalizado. El mensaje de error personalizado te ayuda a averiguar el problema rápidamente.
value = 2_000
if value > 1_000:
# raise the ValueError
raise ValueError("Please add a value lower than 1,000")
else:
print("Congratulations! You are the winner!!")
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
----> 4 raise ValueError("Please add a value lower than 1,000")
5 else:
6 print("Congratulations! You are the winner!!")
ValueError: Please add a value lower than 1,000
Ejemplo de excepción
También podemos lanzar cualquier excepción incorporada aleatoria de Python si se cumple la condición. En nuestro caso, hemos planteado una Excepción genérica con el mensaje de error.
if value > 1_000:
# raise the Exception
raise Exception("Please add a value lower than 1,000")
else:
print("Congratulations! You are the winner!!")
---------------------------------------------------------------------------
Exception Traceback (most recent call last)
----> 3 raise Exception("Please add a value lower than 1,000")
4 else:
5 print("Congratulations! You are the winner!!")
Exception: Please add a value lower than 1,000
Ejemplo de tratamiento de una excepción planteada
También podemos crear nuestra excepción personalizada y manejar la excepción utilizando el bloque try
-except
.
En el ejemplo, hemos añadido un ejemplo de error de valor bajo la declaración try
.
Entonces, ¿cómo funcionará? En lugar de lanzar la excepción y terminar el programa, mostrará el mensaje de error que hemos proporcionado.
value = 2_000
try:
if value > 1_000:
# raise the ValueError
raise ValueError("Please add a value lower than 1,000")
else:
print("Congratulations! You are the winner!!")
# if false then raise the value error
except ValueError as e:
print(e)
Este tipo de manejo de excepciones nos ayuda a prepararnos para los errores que no cubre Python y que son específicos de los requisitos de tu aplicación.
Please add a value lower than 1,000
¿Qué hay de nuevo en Python 3.10 y 3.11 para el manejo de excepciones?
Se han añadido algunas novedades importantes a las versiones más recientes de Python, como la 3.10 y la 3.11, desde que se escribió originalmente la entrada del blog:
1. Concordancia estructural de patrones en Python 3.10: Python 3.10 introdujo la concordancia de patrones estructurales, que puede utilizarse para gestionar las excepciones de forma más elegante mediante la concordancia de tipos de error en una sentencia match
. Esto es especialmente útil cuando se tratan varios tipos de excepción de forma más legible. Ejemplo:
try:
result = 1 / 0
except Exception as e:
match e:
case ZeroDivisionError():
print("You cannot divide by zero.")
case NameError():
print("Variable not defined.")
case _:
print("An unexpected error occurred.")
2. Localización precisa de errores en las trazas (Python 3.11): Las trazas de Python 3.11 muestran ahora ubicaciones precisas de los errores, lo que facilita la depuración de las excepciones.
- Antes de Python 3.11:
value = (1 + 2) * (3 / 0)
- Retroceso:
ZeroDivisionError: division by zero
- Python 3.11: Los rastreos señalan la subexpresión exacta que provoca la excepción:
ZeroDivisionError: division by zero
(1 + 2) * (3 / 0)
^
3. Grupos de excepción y except*
(Python 3.11): Python 3.11 introdujo los grupos de excepciones para manejar múltiples excepciones en un solo bloque utilizando except*
. Esto es útil para gestionar código asíncrono o situaciones en las que se pueden producir varias excepciones. Ejemplo:
try:
raise ExceptionGroup("Multiple errors", [ValueError("Bad value"), TypeError("Bad type")])
except* ValueError as ve:
print(f"Handling ValueError: {ve}")
except* TypeError as te:
print(f"Handling TypeError: {te}")
4. Método add_note
para excepciones (Python 3.11): Las excepciones tienen ahora un método add_note()
, que permite a los desarrolladores añadir notas personalizadas a las excepciones para una mejor depuración. Ejemplo:
try:
raise ValueError("Invalid input")
except ValueError as e:
e.add_note("This happened while processing user input.")
e.add_note("Consider validating input before processing.")
raise
- Retroceso:
ValueError: Invalid input
Notes:
- This happened while processing user input.
- Consider validating input before processing.
5. PEP 654: Mejor gestión de las excepciones anidadas: Con los grupos de excepciones, las excepciones anidadas son ahora más fáciles de depurar y manejar, especialmente en flujos de trabajo complejos como el multiprocesamiento o las tareas asíncronas.
Conclusión
Ambos pruebas unitarias y el manejo de excepciones son las partes fundamentales de la programación en Python que hacen que tu código esté listo para la producción y a prueba de errores. En este tutorial, hemos aprendido sobre excepciones y errores en Python y cómo manejarlos. Además, hemos aprendido sobre bloques try-except anidados complejos y hemos creado bloques de excepción personalizados en función de los requisitos.
Estas herramientas y mecanismos son esenciales, pero la mayor parte del trabajo se realiza mediante sencillos bloques de try
y except
. Donde try
busca las excepciones que provoca el código y except
se encarga de esas excepciones.
Si esto te resulta confuso y no sabes por dónde empezar, completa nuestro curso Introducción a las funciones en Python para comprender el ámbito, las funciones lambda y el tratamiento de errores. También puedes matricularte en el itinerario profesional de Programador de Python para adquirir habilidades de desarrollo profesional y convertirte en un desarrollador profesional de Python.
Aprende Python desde cero
Preguntas frecuentes
¿Cuál es la diferencia entre un error y una excepción en Python?
Un error en Python suele ser un problema más grave que impide que el programa continúe, como un error de sintaxis, que indica que la estructura del código es incorrecta. Una excepción, por otra parte, es una condición que interrumpe el flujo normal del programa, pero que puede manejarse dentro del programa mediante bloques try-except, permitiendo que el programa continúe ejecutándose.
¿Puedes atrapar varias excepciones en un solo bloque try-except?
Sí, Python te permite atrapar varias excepciones en un solo bloque try-except utilizando una tupla de tipos de excepción. Por ejemplo: except (TypeError, ValueError):
. De este modo, podrás gestionar un TypeError
o un ValueError
en el mismo bloque.
¿Cómo puedes crear una excepción personalizada en Python?
Puedes crear una excepción personalizada definiendo una nueva clase que herede de la clase incorporada Exception
. Por ejemplo:
class MyCustomError(Exception):
pass
¿Para qué sirve el bloque else en una estructura try-except?
El bloqueelse
se ejecuta si el bloquetry
no lanza una excepción. Es útil para el código que sólo debe ejecutarse si el bloque try
tiene éxito, manteniendo el código limpio y separando la gestión de errores de la ruta de ejecución normal.
¿Por qué es importante el bloque finally en el tratamiento de excepciones?
El bloquefinally
se ejecuta siempre, independientemente de que se produzca o no una excepción. Se suele utilizar para acciones de limpieza, como cerrar archivos o liberar recursos, para garantizar que estas acciones se realizan en todas las circunstancias.
¿Cómo puedes suprimir excepciones en Python?
Puedes suprimir las excepciones utilizando el gestor de contextocontextlib.suppress
. Te permite especificar los tipos de excepción que deben ignorarse. Por ejemplo:
from contextlib import suppress
with suppress(FileNotFoundError):
open('non_existent_file.txt')
¿Qué ocurre si no se captura una excepción en un programa Python?
Si una excepción no se captura, se propaga por la pila de llamadas y, si queda sin gestionar, termina el programa, imprimiendo un rastreo en la consola que muestra dónde se produjo la excepción.
¿Puedes volver a lanzar una excepción después de atraparla?
Sí, puedes volver a lanzar una excepción utilizando la sentencia raise
sin argumentos en un bloqueexcept
. Esto es útil cuando quieres registrar un error o realizar otras acciones antes de permitir que la excepción siga propagándose.
¿Hay alguna forma de manejar todas las excepciones en Python?
Aunque es posible atrapar todas las excepciones utilizando una cláusulaexcept:
desnuda , generalmente no se recomienda porque puede atrapar excepciones inesperadas y dificultar la depuración. Es mejor atrapar excepciones específicas o utilizar except Exception:
para evitar atrapar excepciones de salida del sistema como SystemExit
y KeyboardInterrupt
.
¿Cómo se diferencia entre un error de sintaxis y las excepciones en tiempo de ejecución en cuanto al momento en que se producen?
Los errores de sintaxis se detectan en tiempo de compilación, lo que significa que el intérprete de Python los detecta antes de que el programa empiece a ejecutarse. Las excepciones en tiempo de ejecución se producen durante la ejecución del programa cuando el intérprete encuentra una operación que no puede realizar, como dividir por cero o acceder a una variable inexistente.
Soy un científico de datos certificado que disfruta creando aplicaciones de aprendizaje automático y escribiendo blogs sobre ciencia de datos. Actualmente me centro en la creación de contenidos, la edición y el trabajo con grandes modelos lingüísticos.
¡Aprende más sobre Python con estos cursos!
curso
Intermediate Python
curso
Introduction to Importing Data in Python
tutorial
21 herramientas esenciales de Python
tutorial
Tutorial sobre cómo trabajar con módulos en Python
Nishant Kumar
8 min
tutorial
Sentencias IF, ELIF y ELSE de Python
tutorial
Una Introducción al Subproceso Python: Conceptos básicos y ejemplos
tutorial
if...elif...else en el tutorial de Python
DataCamp Team
4 min
tutorial