Los errores son solo valores con mala actitud
Cuando algo va mal en Python — dividir por cero, leer un archivo que falta, parsear un número malo — el runtime crea un objeto excepción y empieza a desenrollar la pila de llamadas hasta que algo lo capture. Si nada lo hace, tu programa termina e imprime un traceback.
Las excepciones no son malas en sí. Son cómo Python señala "no puedo continuar con esta operación; aquí tienes el motivo". Tu trabajo es decidir, caso por caso, cuáles sabes cómo manejar y cuáles deberías dejar escalar.
La forma básica
try:abre el bloque de código arriesgado.except ValueError:captura esa excepción específica si se lanza dentro deltry.- Si no se lanza ninguna excepción, el
exceptse salta por completo.
Ejecuta el fragmento con 42 — funciona. Ejecútalo con hello — corre el manejador.
Capturar excepciones específicas
Python tiene una jerarquía de tipos de excepción. Unas cuantas con las que te encontrarás a menudo:
ValueError— un valor estaba mal de alguna forma (int("abc"), argumentos fuera de rango).TypeError— se usó el tipo equivocado ("hi" + 3).KeyError— no se encontró una clave de dict.IndexError— un índice de secuencia estaba fuera de rango.FileNotFoundError— un archivo no existe.ZeroDivisionError— se intentó dividir por cero.AttributeError— un objeto no tiene el atributo pedido.
Captura la específica que sepas manejar:
Puedes capturar varias excepciones en una cláusula pasando una tupla:
Fíjate en as e. Eso ata el objeto excepción a e para que puedas inspeccionar su mensaje o atributos.
Evita capturar todo
Un except: a secas captura literalmente cualquier cosa, incluidos KeyboardInterrupt (tu Ctrl-C) y salidas a nivel de sistema. No lo uses.
except Exception: es un poco mejor, pero sigue siendo peligroso — se traga bugs que no anticipaste y oculta la fuente real de los problemas:
# No hagas esto sin una razón realmente buena.
try:
do_something()
except Exception:
pass
La jugada correcta es casi siempre capturar la excepción específica de la que sabes cómo recuperarte. Si una excepción que no esperabas llega al tope de tu programa, el traceback te dice exactamente qué fue mal — eso es una feature, no un bug.
else y finally
La sentencia try tiene dos cláusulas opcionales más:
elsese ejecuta si el bloquetryterminó sin lanzar.finallyse ejecuta sin importar qué — excepción o no.
else es el sitio más limpio para código "solo en éxito" — no quieres que un bloque try haga más que la parte que realmente puede fallar. finally es para limpieza que debe ejecutarse incluso si el try falla: cerrar un recurso, liberar un lock, restaurar estado.
Lanzar excepciones tú mismo
Usa raise para señalar un error en tu propio código:
Elige un tipo de excepción que encaje con lo que fue mal. Recurre a los incorporados primero — ValueError, TypeError, FileNotFoundError — antes de definir tu propia clase.
Definir tu propia excepción
Cuando los incorporados no capturan el significado, define una excepción personalizada:
Hereda de Exception (o de un incorporado más específico) y ponle una docstring a la clase. Eso suele ser todo lo que necesitas. Las excepciones personalizadas dejan a quien llama capturar solo el error que tiene sentido en su dominio.
raise ... from ...: excepciones encadenadas
Cuando una excepción dispara otra, mantén la cadena:
El from e adjunta el error original. Cuando el traceback se imprime, Python muestra ambos — el ConfigError que salió a la superficie y el FileNotFoundError que lo causó. Ese tipo de rastro es invaluable al depurar.
Context managers: la forma más limpia de limpiar
finally está bien, pero para recursos como archivos, un context manager (lo que usa with) es casi siempre mejor:
# versión con finally
f = open("data.txt")
try:
data = f.read()
finally:
f.close()
# versión con with
with open("data.txt") as f:
data = f.read()
Ambas son seguras. La forma with es más corta y se aplica automáticamente. Recurre a finally solo cuando estés haciendo algo que la librería estándar no envuelve ya en un context manager.
Cuándo no capturar
Capturar una excepción es una decisión — estás diciendo "puedo manejar esto". Si no puedes, deja que la excepción se propague. Código como este es casi siempre un error:
try:
do_work()
except Exception:
pass # ignorar silenciosamente todo
Silenciar errores hace invisibles los bugs. Es mejor crashear ruidosamente que cojear en un estado inconsistente.
Para cerrar
try/exceptte deja manejar errores de los que te puedes recuperar.- Captura excepciones específicas, no
Exceptiona lo bruto. raiseseñala errores en tu propio código.- Los bloques
withreemplazan la mayor parte de limpieza confinally. - En caso de duda, deja que la excepción se propague.
Siguiente: un recorrido por los errores específicos que Python lanza más a menudo — KeyError, ValueError, ModuleNotFoundError y unos cuantos más — más los hábitos de depuración que los arreglan rápido.
Preguntas frecuentes
¿Cómo manejo errores en Python?
Envuelve código arriesgado en un bloque try y captura la excepción específica en un bloque except: try: risky() except ValueError: .... El else opcional se ejecuta si no ocurrió ninguna excepción; finally se ejecuta de una u otra forma, para limpieza.
¿Debería capturar Exception para ir sobre seguro?
No. Un except: a secas o except Exception: oculta bugs que no anticipaste. Captura la excepción específica de la que sepas recuperarte y deja que todo lo demás se propague para que veas el problema real.
¿Cuál es la diferencia entre raise y raise from?
raise NewError(...) lanza una excepción nueva. raise NewError(...) from original mantiene la excepción original adjunta como causa, que Python muestra en el traceback. Usa from cuando un error de bajo nivel haya disparado uno de alto nivel que quieres exponer.