Para manejar los errores de entorno, que no dependen del programador, sino que los genera el usuario, vamos a emplear las excepciones. Las excepciones en Python son eventos que interrumpen el flujo normal de un programa cuando ocurre un error (por ejemplo, dividir entre cero o intentar acceder a un fichero que no existe o que no está localizado en la carpeta en la que lo estamos buscando). En lugar de dejar que el programa falle sin control, Python permite capturar y manejar estas situaciones con bloques try-except, y complementar el control con else y finally para ejecutar código cuando no hay errores o siempre, respectivamente. También es posible lanzar errores de forma explícita con raise y definir excepciones propias para representar problemas específicos de tu aplicación.
Bloque try-except
En el bloque try pondremos las instrucciones que pueden generar la excepción y en el bloque except las instrucciones para gestionar dicha excepción en el caso que se produzca.
Ejemplo:
fichero="Planetas.txt"
try:
with open(fichero) as objetoFichero:
contenido=objetoFichero.read()
except FileNotFoundError:
print("Ufff, parece que el fichero ",fichero," no existe")
print(contenido)
Se pueden capturar distintos tipos de excepciones con múltiples except. Hay que colocar primero las excepciones más específicas y al final las más genéricas, ya que las clausulas except se evalúan en orden, y cuando coincide se ejecuta y no se evalúan más clausula except.
fichero = "planetas.txt"
try:
with open(fichero) as fh:
contenido = fh.read()
except FileNotFoundError as e:
print(f"No se encuentra el fichero: {e.filename}")
except PermissionError:
print("No tienes permisos para abrir el fichero.")
except OSError as e:
print(f"Otro error de E/S: {e}")
except Exception as e:
print(f"Error inesperado: {type(e).__name__}: {e}")
else:
print(contenido)
finally:
print("Este bloque se ejecuta SIEMPRE (para limpieza, cerrar recursos, etc.).")
La última clausula except, es una captura genérica, que recogería cualquier otra excepción que no se halla chequeado antes.
Clausula else
Más correcto sería emplear el bloque else para que se ejecuten las instrucciones en el caso de que no se produzca ninguna excepción:
fichero="Planetas.txt"
try:
with open(fichero) as objetoFichero:
contenido=objetoFichero.read()
except FileNotFoundError:
print("Ufff, parece que el fichero ",fichero," no existe")
else:
print(contenido)
Clausula finally
Las instrucciones en el bloque finally siempre se ejecutan, haya o no excepción, incluso si hay return en try/except. Conviene usarla cuando tengamos que garantizar alguna operación de limpieza, halla o no éxito. Por ejemplo, cerrar un fichero o cerrar una conexión a una base de datos.
Ejemplo:
f = open("data.txt")
try:
data = f.read()
except FileNotFoundError:
print("Archivo no encontrado")
finally:
f.close()
Encadenamiento(raise, raise from)
El encadenamiento y relanzamiento de excepciones en Python permite propagar errores con contexto. Se puede atrapar una excepción de bajo nivel, añadir información útil y volver a lanzarla. Con raise se relanza la excepción actual o una nueva, y con raise from se crea un encadenamiento explícito que preserva la causa original, lo que facilita el diagnóstico de errores.
def cargar_config(ruta):
try:
import json
with open(ruta, "r", encoding="utf-8") as fh:
return json.load(fh)
except FileNotFoundError as e:
raise RuntimeError("No se pudo cargar la configuración") from e
try:
cargar_config("config.json")
except RuntimeError as e:
print(f"Fallo: {e} (causa: {e.__cause__})")
Excepciones frecuentes
Las excepciones más habituales que podemos encontrarnos son:
| Excepción | ¿Cuándo ocurre? | Ejemplo |
| ValueError | Valor con tipo correcto pero contenido inválido | int(‘abc’) |
| TypeError | Operación no soporta por el tipo de objeto al que se aplicada | ‘a’ + 5 |
| KeyError | Clave inexistente en diccionario | d[‘x’] |
| IndexError | Índice fuera de rango | [1,2][7] |
| FileNotFoundError | Fichero no se encuentra en la ruta indicada | open(‘data.txt’) |
| PermissionError | Sin permisos de acceso | open(‘/root/privado’) |
| ZeroDivisionError | División por cero | 7/0 |
| OSError | Errores de sistema/IO | os.remove(‘bloqueado’) |
| KeyboardInterrupt | Interrupción manual (Ctrl+C) |
NOTA:
Este post es parte de la colección “Python”. Puedes ver el índice de esta colección aquí.