2009-12-06 15 views
12

Ci sono alcune domande simili, ma nessuna fornisce la risposta che richiedo.Aumenta le eccezioni non gestite in una discussione nel thread principale?

Se si creano thread tramite threading.Thread, che generano eccezioni non gestite, tali thread sono terminati. Desidero mantenere la stampa predefinita dei dettagli delle eccezioni con la traccia dello stack, ma abbattere anche l'intero processo.

Ho considerato che potrebbe essere possibile catturare tutte le eccezioni nei thread e controrilanciare sull'oggetto thread principale, o forse è possibile eseguire manualmente la gestione delle eccezioni predefinita e quindi aumentare un SystemExit sul main filo.

Qual è il modo migliore per farlo?

risposta

15

Ho scritto circa Re-throwing exceptions in Python, incluso qualcosa di simile a questo come esempio.

Sul thread di lavoro si esegue questa operazione (Python 2.x, vedere di seguito per la versione 3.x di Python):

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

e sul thread principale si esegue questa operazione:

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

L'eccezione apparirà nel thread principale proprio come se fosse stato generato nel thread worker.

Python 3.x:

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

e sul thread principale:

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

non intendi lanciare 'thrdobj.exc_info' nel thread principale, e perché rilasciare il tipo di eccezione quando rethrow? –

+0

vedo ora, ho dovuto leggere la dichiarazione di aumento 3arg. ma la domanda su 'self' è ancora valida, grazie per una buona risposta, lo proverò –

+0

Non sono sicuro di quale sia la tua domanda su di te. Questo codice proviene da un oggetto che viene utilizzato per rinviare il lavoro su un thread di lavoro, quindi lo stesso oggetto esegue il codice nel worker e nei thread principali. –

9

L'unica eccezione un thread secondario può aumentare in modo affidabile nel thread principale è KeyboardInterrupt: il modo in cui il thread secondario lo è chiamando la funzione thread.interrupt_main(). Non c'è modo di associare informazioni extra (sul motivo dell'eccezione) all'oggetto eccezione che viene generato - il secondo è sempre un semplice KeyboardInterrupt. Pertanto, è necessario nascondere tali informazioni altrove, ad es. su un'istanza dedicata di Queue.Queue - tali informazioni potrebbero includere i risultati che il thread secondario può ottenere tramite sys.exc_info() e qualsiasi altra cosa che si possa trovare utile, naturalmente.

Il thread principale dovrà recuperare le informazioni extra (e tener conto che la coda sarà vuota se l'interruzione della tastiera è in realtà dovuta al controllo di C-user o simili, quindi usa get_nowait e preparati per gestire un'eccezione Queue.Empty, ad esempio), formattarlo come si desidera e terminare (se tutti i thread secondari sono daemon s, l'intero processo termina quando termina il thread principale).

+0

collegamento alla documentazione di threading aggiornato: https://docs.python.org/3.6/library/_thread.html?highlight=interrupt_main#_thread.interrupt_main – user2682863