2009-12-06 11 views
12

Hay algunas preguntas similares, pero ninguna proporciona la respuesta que requiero.¿Suceder excepciones no controladas en un hilo en el hilo principal?

Si creo hilos a través de threading.Thread, que arrojan excepciones que no se han manejado, esos hilos terminan. Deseo conservar la impresión predeterminada de los detalles de la excepción con el seguimiento de la pila, pero también reducir todo el proceso.

He pensado que podría ser posible capturar todas las excepciones en los hilos, y volver a subir ellos en el objeto principal de hilo, o tal vez es posible realizar manualmente el manejo de excepciones por defecto, y luego levantar una SystemExit en la principal hilo.

¿Cuál es la mejor manera de hacerlo?

Respuesta

15

Escribí sobre Re-throwing exceptions in Python, incluyendo algo muy parecido a esto como un ejemplo.

En el subproceso de trabajo que hace esto (Python 2.x, ver más abajo para la versión 3.x de Python):

try: 
    self.result = self.do_something_dangerous() 
except Exception, e: 
    import sys 
    self.exc_info = sys.exc_info() 

y en el hilo principal de hacer esto:

if self.exc_info: 
    raise self.exc_info[1], None, self.exc_info[2] 
return self.result 

La excepción aparecerá en el hilo principal como si hubiera sido subida en el hilo del trabajador.

Python 3.x:

try: 
    self.result = self.do_something_dangerous() 
except Exception as e: 
    import sys 
    self.exc_info = sys.exc_info() 

y en el hilo principal:

if self.exc_info: 
    raise self.exc_info[1].with_traceback(self.exc_info[2]) 
return self.result 
+0

¿No quiere tirar 'thrdobj.exc_info' en el hilo principal, y ¿por qué soltar el tipo de excepción cuando vuelve a lanzar? –

+0

veo ahora, tuve que leer en 3arg subir declaración. pero la pregunta sobre "yo" sigue en pie, gracias por una buena respuesta, lo intentaré –

+0

No estoy seguro de cuál es su pregunta sobre sí mismo. Este código proviene de un objeto que se utiliza para aplazar el trabajo en un hilo de trabajo, por lo que el mismo objeto ejecuta código en el trabajador y en los hilos principales. –

9

La única excepción de una rosca secundaria puede aumentar de forma fiable en el hilo principal es KeyboardInterrupt: la forma en que el El hilo secundario lo hace llamando a la función thread.interrupt_main(). No hay forma de asociar información adicional (sobre el motivo de la excepción) con el objeto de excepción que se genera; el último siempre es simplemente KeyboardInterrupt. Por lo tanto, debe esconder esa información en otro lugar, p. en una instancia dedicada de Queue.Queue - esa información puede incluir los resultados que el hilo secundario puede obtener a través de sys.exc_info(), y cualquier otra cosa que encuentre útil, por supuesto.

El hilo principal deberá recuperar esa información adicional (y tener en cuenta que la cola estará vacía si la interrupción del teclado se debe realmente al usuario que golpea el control-C o similar, así que use get_nowait y esté listo para tratar con una excepción Queue.Empty, por ejemplo), formatéelo como lo desee y termine (si todos los hilos secundarios son daemon s, todo el proceso finaliza cuando finaliza el hilo principal).

+0

actualización del enlace de documentación de threading: https://docs.python.org/3.6/library/_thread.html?highlight=interrupt_main#_thread.interrupt_main – user2682863

Cuestiones relacionadas