Pregunta 1¿Qué imprime el siguiente código?try:
raise ValueError("NG")
print("A")
except ValueError as e:
print(e)
print("B")
Lanzar excepciones con raise / clases de excepción personalizadas
Aprende a lanzar tus propias excepciones en Python con raise y a definir clases de excepción personalizadas.
En el artículo anterior sobre try / except, vimos el lado receptor de una excepción.
Este artículo cubre raise — el lado emisor, donde haces aflorar una excepción tú mismo. Cuando lanzas una excepción ante una entrada inválida o un estado inesperado, se garantiza que el que llama se enterará vía try / except.
Lo básico de raise
Escribir raise ClaseDeExcepción("mensaje") lanza esa excepción justo en ese momento. En cuanto raise se ejecuta, el resto del código se salta y el control salta al except que coincida.
El mensaje es opcional, pero incluir por qué falló permite al receptor leerlo vía except ... as e.
# Lanza un ValueError y captúralo en el lado receptor
try:
raise ValueError("Edad inválida")
print("nunca se alcanza")
except ValueError as e:
print(f"Capturado: {e}")
# Salida: Capturado: Edad inválida
# Cualquier excepción integrada funciona tal cual
# Comunes: ValueError / TypeError / KeyError / IndexError
Validar con if + raise
raise se usa con más frecuencia para la validación de entrada. Cuando un if detecta algo inválido, raise de inmediato y devuelve la llamada al que la hizo. Es una técnica idiomática en funciones (se ve más adelante), donde lanzar dentro de una función notifica al que llama de argumentos incorrectos.
El flujo — el camino normal pasa de largo; el camino anómalo lanza y se detiene — es el patrón central para la validación en código de producción.
Comprueba la entrada una condición a la vez; en el instante en que algo falla, raise y para. Solo cuando todas las condiciones pasan se procede con el procesamiento normal. Como gana el primer raise, el orden de las comprobaciones marca su prioridad.
# Valida el precio de un producto: 0 o menos es un error
price = -500
try:
if price < 0:
raise ValueError(f"El precio debe ser 0 o mayor (se recibió: {price})")
if not isinstance(price, int):
raise TypeError(f"El precio debe ser entero (tipo recibido: {type(price).__name__})")
print(f"Registrado: {price}")
except ValueError as e:
print(f"Error de valor: {e}")
except TypeError as e:
print(f"Error de tipo: {e}")
# Salida: Error de valor: El precio debe ser 0 o mayor (se recibió: -500)
Una guía rápida sobre qué excepción integrada lanzar: usa ValueError cuando el valor sea incorrecto, TypeError cuando el tipo no coincida con lo esperado, y KeyError / IndexError cuando la clave o el elemento objetivo falte en un dict o lista.
Definir una clase de excepción personalizada
A veces las excepciones integradas por sí solas hacen difícil saber qué validación falló. Definir tu propia clase de excepción te permite capturarla con precisión en el lado del except.
La forma es class NombreError(Exception): con pass (vacío) como cuerpo — eso es todo. Cubriremos las clases en profundidad en el próximo capítulo de programación orientada a objetos, pero para clases de excepción esta única línea basta.
# Define una excepción personalizada (basta 1 línea)
class InvalidAgeError(Exception):
pass
class DuplicateUserError(Exception):
pass
registered_users = ["ana", "carlos"]
new_user = "ana"
new_age = -1
try:
if new_age < 0:
raise InvalidAgeError(f"La edad debe ser 0 o mayor: {new_age}")
if new_user in registered_users:
raise DuplicateUserError(f"Ya registrado: {new_user}")
print(f"Registrado: {new_user}")
except InvalidAgeError as e:
print(f"Error de edad: {e}")
except DuplicateUserError as e:
print(f"Error de duplicado: {e}")
# Salida: Error de edad: La edad debe ser 0 o mayor: -1
Las excepciones personalizadas fijan Exception como clase padre
El Exception entre paréntesis nombra a la clase padre. Poner Exception ahí hace que tu clase personalizada obtenga automáticamente las características estándar de excepción — puede llevar un mensaje, es capturable por un except Exception genérico, etcétera. El mecanismo padre / hijo en sí (la herencia) se cubre en el capítulo de programación orientada a objetos, pero esta única línea es todo lo que necesitas para definir una excepción.
En este artículo aprendiste cómo lanzar excepciones tú mismo con raise, el patrón if + raise para la validación, y cómo definir una clase de excepción personalizada con Exception fijada como clase padre.
A continuación, miraremos def — que ya ha aparecido varias veces — como tema de primera categoría y aprenderemos a agrupar y reutilizar lógica con funciones.
Verificación de conocimientos
Responde cada pregunta una a una.
Pregunta 2¿Qué excepción integrada es la más apropiada cuando el valor es inválido?
Pregunta 3¿Cuál es el mayor beneficio de usar una excepción personalizada class MyError(Exception): pass?