Las excepciones personalizadas simples no se generan de la misma manera que las integradas.
Tengo un programa con multiproceso – 4 procesos, y dentro de éstos genero múltiples hilos, por lo que también es multihilado. No tengo mucha experiencia en el seguimiento y depuración de estos, pero ahora estoy empezando a hacerlo. Sin embargo, tengo este bloque de código en mi servidor TCP:
Tengo excepciones como esta:
class Error(Exception):
"""Excepción básica"""
class NoDataReceived(Error):
"""Lanzada cuando no hay datos"""
Ahora el código:
try:
...
if True:
raise ValueError('No se recibieron datos') # <--- esto imprimirá
# raise NoDataReceived('No hay datos') # <--- cuando uso esto, no imprimirá
except ValueError as err: # integrada
print('err')
except NoDataReceived as err: # personalizada
print('err') # ¡NO imprime..?
El problema es que cuando planteo un ValueError, lo imprime, pero cuando planteo un NoDataReceived personalizado, no imprime nada.
Necesito decir que es un programa multihilado y multiprocesado (hilos dentro de un proceso), si corro este pedazo de código en un script simple y de un solo hilo, funciona como debería. No me gusta este comportamiento, antes de construir algo sobre esto, necesito entenderlo mejor. Sé que podría usar sys_traceback, pero realmente quiero hacer que esto funcione como debería, simplemente.
¿Tienes alguna explicación para mí, amigos?
[Python 3.8]
Gracias por tu tiempo, Q.
davy.ai
Es posible que la excepción personalizada
NoDataReceived
no esté siendo atrapada porque es levantada en un hilo o proceso separado que no está siendo monitoreado por el bloque try-except en el hilo/proceso principal.Para asegurarnos de que las excepciones sean atrapadas en todos los hilos y procesos, una posible solución es implementar un manejador de errores global que atrape todas las excepciones no manejadas e imprima su rastreo de pila. Esto se puede hacer registrando el manejador usando la función
sys.excepthook
al comienzo del programa:Esto hará que todas las excepciones no manejadas se impriman con sus rastreos de pila, independientemente del hilo o proceso en el que se hayan levantado.
Alternativamente, si desea atrapar la excepción en el hilo/proceso principal pero no está siendo capturada por el bloque try-except, es posible que la excepción se esté levantando en un método o función separados que se están llamando de manera asíncrona (es decir, con
asyncio
,concurrent.futures
u otras bibliotecas similares). En este caso, es posible que la excepción deba ser atrapada utilizando un mecanismo diferente diseñado para el código asíncrono, comoasyncio.create_task()
oconcurrent.futures.as_completed()
.