2013-08-21 12 views
11

Ho una serie di attività da eseguire in parallelo, ma alla fine di esse, ho bisogno di sapere se uno qualsiasi dei thread ha generato un'eccezione. Non ho bisogno di gestire direttamente l'eccezione, ho solo bisogno di sapere se uno dei fili non riuscita con un'eccezione, in modo da poter in modo pulito terminare lo scriptControlla se un thread python ha generato un'eccezione

Ecco un semplice esempio:

#!/usr/bin/python 

from time import sleep 
from threading import Thread 

def func(a): 
    for i in range(0,5): 
     print a 
     sleep(1) 

def func_ex(): 
    sleep(2) 
    raise Exception("Blah") 


x = [Thread(target=func, args=("T1",)), Thread(target=func, args=("T2",)), Thread(target=func_ex, args=())] 

print "Starting" 
for t in x: 
    t.start() 

print "Joining" 
for t in x: 
    t.join() 


print "End" 

Prima di "Fine", voglio ripetere i thread, vedere se c'è qualche errore, e poi decidere se posso continuare con lo script, o se devo uscire a questo punto.

Non ho bisogno di intercettare l'eccezione o di interrompere gli altri thread, ho solo bisogno di sapere alla fine se qualche errore.

risposta

7

Quando la chiamata join() restituisce un thread, lo stack del thread è stato svolto e tutte le informazioni sulle eccezioni sono state perse. Pertanto, sfortunatamente, dovrai fornire il tuo meccanismo per registrare le eccezioni; alcune tecniche sono discusse here.

1

Una tecnica semplice per le situazioni in cui non è necessario gestire l'eccezione consiste nell'utilizzare un elenco globale e aggiungervi informazioni pertinenti. Il tuo codice sarebbe diventato qualcosa di simile:

#!/usr/bin/python 

from time import sleep 
from threading import Thread, current_thread #needed to get thread name or whatever identifying info you need 

threadErrors = [] #global list 

def func(a): 
    for i in range(0,5): 
     print a 
     sleep(1) 

def func_ex(): 
    global threadErrors #if you intend to change a global variable from within a different scope it has to be declared 
    try: 
     sleep(2) 
     raise Exception("Blah") 
    except Exception, e: 
     threadErrors.append([repr(e), current_thread.name]) #append a list of info 
     raise #re-raise the exception or use sys.exit(1) to let the thread die and free resources 

x = [Thread(target=func, args=("T1",)), Thread(target=func, args=("T2",)), Thread(target=func_ex, args=())] 

print "Starting" 
for t in x: 
    t.start() 

print "Joining" 
for t in x: 
    t.join() 

if len(threadErrors) > 0: #check if there are any errors 
    for e in threadErrors: 
     print(threadErrors[e][0]+' occurred in thread: '+threadErrors[e][1]) 
     #do whatever with each error info 
else: 
    #there are no errors so do normal clean-up stuff 

#do clean-up that should happen in either case here 

print "End" 

Nota: variabili globali sono generalmente considerati come scarsa tecnica, ma sono un semplice meccanismo per la comunicazione tra i thread. Devi solo ricordare che se un thread sta inviando informazioni da questa rotta, l'altro thread deve cercarlo.

Problemi correlati