Python Try...Except
Aprende los bloques try, except, else y finally de Python con ejemplos claros. Maneja ZeroDivisionError, ValueError, FileNotFoundError y más.
Cuando Python encuentra un error en tiempo de ejecución, lanza una excepción — un objeto que representa lo que salió mal. Sin ningún manejo, una excepción termina tu programa de inmediato. La sentencia try...except te permite capturar estas excepciones, responder a ellas de forma elegante y mantener tu programa en funcionamiento.
Este capítulo cubre:
- El bloque
try/except— capturar una excepción específica - Capturar detalles de la excepción con
as - Múltiples cláusulas
excepty capturar varias excepciones a la vez - El bloque
else— código que se ejecuta solo cuando no ocurre ninguna excepción - El bloque
finally— código de limpieza que siempre se ejecuta - Excepciones integradas comunes y cuándo ocurren
- Relanzar excepciones
- Buenas prácticas y errores comunes
El bloque try...except básico
Envuelve el código que podría fallar en un bloque try. Si Python lanza una excepción, la ejecución salta al bloque except correspondiente en lugar de terminar abruptamente.
Salida:
Error: division by zeroPython intenta la división, lanza ZeroDivisionError, y el bloque except lo maneja. La cláusula as e vincula el objeto de excepción a e para que puedas inspeccionar o registrar el mensaje.
Si el bloque try tiene éxito, el bloque except se omite por completo.
Capturar un tipo de excepción específico
Siempre nombra el tipo de excepción que esperas. Capturar un tipo con nombre hace tu intención clara y evita ocultar accidentalmente errores no relacionados.
try:
number = int("abc")
except ValueError as e:
print(f"Could not convert: {e}")Salida:
Could not convert: invalid literal for int() with base 10: 'abc'int("abc") lanza ValueError porque "abc" no es un entero válido. Especificar ValueError en la cláusula except significa que cualquier otra excepción inesperada seguirá propagándose y aparecerá como un error en lugar de ser silenciada.
Múltiples cláusulas except
Un único bloque try puede tener varias cláusulas except — Python las verifica de arriba a abajo y ejecuta la primera coincidencia.
def safe_index(items, index):
try:
return items[index]
except IndexError:
print("Index out of range.")
except TypeError:
print("Index must be an integer.")
safe_index([1, 2, 3], 10) # IndexError
safe_index([1, 2, 3], "a") # TypeErrorSalida:
Index out of range.
Index must be an integer.El orden importa: coloca los tipos de excepción más específicos antes que los más amplios para que el manejador específico se ejecute primero.
Capturar múltiples excepciones en una cláusula
Cuando dos o más excepciones merecen la misma respuesta, agrúpalas en una tupla:
try:
value = int("not-a-number")
except (ValueError, TypeError) as e:
print(f"Input error: {e}")Salida:
Input error: invalid literal for int() with base 10: 'not-a-number'El bloque else
El bloque else se ejecuta solo cuando el bloque try se completa sin lanzar ninguna excepción. Úsalo para el código que debe ejecutarse en caso de éxito pero que no necesita protección contra errores:
try:
result = 10 / 2
except ZeroDivisionError:
print("Cannot divide by zero.")
else:
print(f"Division succeeded. Result: {result}")Salida:
Division succeeded. Result: 5.0Mantener la lógica del camino exitoso en else (en lugar de al final de try) evita capturar accidentalmente excepciones que el propio código del camino exitoso podría lanzar.
El bloque finally
El bloque finally se ejecuta sin importar qué — ya sea que el bloque try tenga éxito, se capture una excepción o una excepción se propague sin capturar. Úsalo para limpieza: cerrar archivos, liberar bloqueos o desconectarse de una base de datos.
try:
result = 10 / 0
except ZeroDivisionError:
print("Error caught.")
finally:
print("This always runs — cleanup goes here.")Salida:
Error caught.
This always runs — cleanup goes here.Incluso si comentas el bloque except, finally se ejecuta antes de que Python propague la excepción.
Estructura completa de un vistazo
try:
# code that may raise an exception
except SomeException as e:
# handle the exception
except (AnotherError, YetAnother):
# handle either of these
else:
# runs only when try succeeded
finally:
# always runsExcepciones integradas comunes
| Excepción | Cuándo ocurre |
|---|---|
ZeroDivisionError | División o módulo por cero |
ValueError | Tipo correcto, valor incorrecto (p. ej. int("abc")) |
TypeError | Operación aplicada al tipo incorrecto |
IndexError | Índice de secuencia fuera de rango |
KeyError | Clave de diccionario no encontrada |
FileNotFoundError | El archivo o directorio no existe |
AttributeError | El objeto no tiene ese atributo |
ImportError | El módulo no puede importarse |
NameError | El nombre de variable no está definido |
Todas estas heredan de la clase base Exception. Puedes capturar Exception para manejar cualquiera de ellas en una sola cláusula, pero prefiere tipos específicos cuando sea posible.
Manejar un archivo faltante
try:
with open("data.txt", "r") as file:
content = file.read()
except FileNotFoundError:
print("Error: File not found.")Salida (cuando data.txt no existe):
Error: File not found.Relanzar una excepción
A veces quieres registrar una excepción o hacer una limpieza parcial, pero aun así dejar que se propague al llamador. Usa un raise sin argumentos dentro de un bloque except:
def process():
try:
result = 10 / 0
except ZeroDivisionError:
print("Logging error...")
raise # re-raises the original ZeroDivisionError
try:
process()
except ZeroDivisionError as e:
print(f"Outer handler caught: {e}")Salida:
Logging error...
Outer handler caught: division by zeroEl raise sin argumentos preserva el traceback original para que la depuración no sea más difícil que sin el manejador.
Capturar la clase base Exception
Puedes usar Exception como captura general para cualquier error que no salga del sistema:
try:
result = 10 / 0
except Exception as e:
print(f"An error occurred: {type(e).__name__}: {e}")Salida:
An error occurred: ZeroDivisionError: division by zerotype(e).__name__ te da el nombre de clase específico incluso cuando capturas a través de la clase base. Esto es útil en manejadores de nivel superior donde quieres registrar cada error inesperado.
Bare except — y por qué evitarlo
Un bare except (sin tipo de excepción) captura literalmente todo, incluyendo KeyboardInterrupt (Ctrl+C) y SystemExit, haciendo que tu programa sea difícil de interrumpir:
# Avoid this pattern
try:
result = 10 / 0
except:
print("Some error occurred")Prefiere except Exception si necesitas una captura amplia, porque aún permite que KeyboardInterrupt y SystemExit se propaguen normalmente.
Buenas prácticas
- Sé específico. Captura el tipo de excepción más estrecho que tenga sentido.
- No silencies excepciones. Como mínimo registra el error; nunca dejes un bloque
exceptvacío. - Usa
elsepara el código del camino exitoso. Esto mantiene el bloquetrylo más pequeño posible. - Usa
finallypara la limpieza. O, mejor aún, usa una sentenciawith— consulta Python with Statement. - Evita el
exceptsin tipo. Usaexcept Exceptionsi necesitas una red amplia. - Relanza cuando sea apropiado. Si no puedes manejar completamente el error, déjalo propagarse con
raise.
Para lanzar excepciones deliberadamente y crear tus propias clases de excepción, consulta Python raise and Custom Exceptions.