如何处理失败的守护进程线程并在不指定超时值的情况下继续主线程



我有两个同时运行的函数作为守护进程线程,它们都将输出放入队列,一旦较快的一个完成,主线程就会继续-较慢的一个要么有值,要么失败,这无关紧要。我们不知道哪一个将首先完成,但我的目标是始终返回具有更快结果的主线程,如果在任何一个线程中都没有引发异常,则这与以下代码都能很好地配合使用。我的问题是处理两者都失败的情况,在这种情况下,我想立即返回到主线程。

def search1(Q_result, name):
raise Exception("search1 raised an exception, not putting any output to the queue...")
result = somefunction()
Q_result.put(result)
def search2(Q_result, name):
raise Exception("search2 raised an exception, not putting any output to the queue...")
result = somefunction()
Q_result.put(result )

import Queue as queue
import threading
Q_result = queue.Queue()  # create a Queue to hold the result(s)
if __name__=='__main__':
t1 = threading.Thread(
target=search1,
args=(Q_result, name),
)
t1.daemon = True
t1.start()

t2 = threading.Thread(
target=search2,
args=(Q_result),
)
t2.daemon = True
t2.start()

try:
res = Q_result.get(timeout=10)
print res
except queue.Empty:
print "Queue is empty, returning to main thread..."

超时后的输出=10秒:

search1 raised an exception, not putting any output to the queue...
search2 raised an exception, not putting any output to the queue...
Queue is empty, returning to main thread...

这种方法有两个问题:

  • 如果两个线程都在比超时时间短的时间内失败,例如在2秒内,那该怎么办?那么我要等待8秒才能返回到主线程,而不是在2秒内返回
  • 如果其中一个搜索线程花费的时间超过了超时时间(我对此没有太多控制权(,并且会返回一个有效的输出,但超时会在线程返回之前杀死它,该怎么办

如何处理?(@ti7,@Arty有什么建议吗?(

您需要在两个worker函数中捕获异常(try/catch(,并将一些特殊的值标记(如None(或一些字符串(如"__BAD_VALUE__"(放入队列中。

然后main检查队列中的第一个结果是否不等于该标记(None(,则第一个好结果已准备就绪,main应打印或将其返回给用户。若队列中的第一个结果似乎是坏的(None(,那个么main应该等待队列中的第二个结果。若第二个并没有坏(不是None(,那个么它将返回给用户,否则两个worker都失败了,main应该报告全部失败,或者以某种方式重做两个API调用的整个过程。

此外,队列获取函数内部仍然需要超时,因为任何工作程序都可以出于某种原因无限期挂起,没有任何例外,如果两个工作程序都挂起了,那么main应该退出并再次报告完全失败,但原因是挂起了工作程序(也不例外(。

下面的完整代码:

在线试用!

import time
name = 'abc'
def search1(Q_result, name):
try:
raise Exception("search1 raised an exception, not putting any output to the queue...")
#result = somefunction()
result = 'first_result'
Q_result.put(result)
except:
Q_result.put(None)
def search2(Q_result, name):
try:
time.sleep(1)
#raise Exception("search2 raised an exception, not putting any output to the queue...")
#result = somefunction()
result = 'second_result'
Q_result.put(result )
except:
Q_result.put(None)

import Queue as queue
import threading
Q_result = queue.Queue()  # create a Queue to hold the result(s)
if __name__=='__main__':
t1 = threading.Thread(
target=search1,
args=(Q_result, name),
)
t1.daemon = True
t1.start()

t2 = threading.Thread(
target=search2,
args=(Q_result, name),
)
t2.daemon = True
t2.start()

try:
res = Q_result.get(timeout = 10)
if res is None:
res = Q_result.get(timeout = 10)
if res is None:
print('Both funcs had exceptions/errors, total failure, do something!')
if res is not None:
print(res)
except queue.Empty:
print('Function has frozen for too long, total failure, do something!')

相关内容

  • 没有找到相关文章