Проверьте, что поток python выбрал исключение
У меня есть набор задач, которые нужно выполнить параллельно, но в конце их мне нужно знать, вызвало ли какое-либо из потоков исключение.
Мне не нужно обрабатывать исключение напрямую, мне просто нужно знать, не сработал ли один из потоков с исключением, поэтому я могу чисто завершить script
Вот простой пример:
#!/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"
Перед "Конец" я хочу выполнить итерацию по потокам, посмотреть, не удалось ли сбой, а затем решить, могу ли я продолжить работу с script, или если мне нужно выйти с этой точки.
Мне не нужно перехватывать исключение или останавливать другие потоки, мне просто нужно знать в конце, если какой-либо сбой.
Ответы
Ответ 1
К моменту вызова join()
в потоке поток стека потоков был размотан, и вся информация об исключениях была потеряна. Таким образом, к сожалению, вам необходимо предоставить свой собственный механизм регистрации исключений; некоторые методы обсуждаются здесь.
Ответ 2
Простым методом для ситуаций, когда вам не нужно обрабатывать исключение, является использование глобального списка и добавление к нему соответствующей информации. Ваш код станет чем-то вроде:
#!/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"
Примечание. глобальные переменные обычно считаются плохой техникой, но они являются простым механизмом для обмена данными между потоками. Вы просто должны помнить, что если один поток отправляет информацию по этому маршруту, другой поток должен искать его.