如何处理失败的守护线程并在不指定超时值的情况下继续主线程?
How to handle failing daemon threads and continue the main thread without specifying a timeout value?
我同时有两个 运行 函数作为守护线程,都将它们的输出放入队列,一旦较快的线程完成,主线程继续 - 较慢的线程要么有价值,要么失败,它没有'没关系。我们不知道哪个会先完成,但我的目标是总是 return 主线程有更快的结果,如果在任何一个线程中都没有引发异常,这与下面的代码一起工作得很好。我的问题是处理两个都失败的情况,在那种情况下,我想立即 return 到主线程。
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 秒 returning 到主线程,而不是 returning 在 2 秒内
- 如果其中一个搜索线程花费的时间比超时时间长(我对此没有太多控制权来处理)并且会 return 具有有效输出,但是超时会在它结束之前终止线程怎么办return它。
你需要在两个工人的函数中捕获异常(try/catch)并将一些特殊的value-marker比如None
或者一些字符串比如"__BAD_VALUE__"
放入队列中。
然后主要检查队列中的第一个结果是否不等于此标记 (None
) 然后第一个好的结果准备就绪并且主要应该打印或 return 它给用户。如果队列中的第一个结果似乎是错误的 (None
),那么 main 应该等待队列中的第二个结果。如果 second 不错(不是 None
),那么它会被 return 发送给用户,否则两个 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!')
我同时有两个 运行 函数作为守护线程,都将它们的输出放入队列,一旦较快的线程完成,主线程继续 - 较慢的线程要么有价值,要么失败,它没有'没关系。我们不知道哪个会先完成,但我的目标是总是 return 主线程有更快的结果,如果在任何一个线程中都没有引发异常,这与下面的代码一起工作得很好。我的问题是处理两个都失败的情况,在那种情况下,我想立即 return 到主线程。
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 秒 returning 到主线程,而不是 returning 在 2 秒内
- 如果其中一个搜索线程花费的时间比超时时间长(我对此没有太多控制权来处理)并且会 return 具有有效输出,但是超时会在它结束之前终止线程怎么办return它。
你需要在两个工人的函数中捕获异常(try/catch)并将一些特殊的value-marker比如None
或者一些字符串比如"__BAD_VALUE__"
放入队列中。
然后主要检查队列中的第一个结果是否不等于此标记 (None
) 然后第一个好的结果准备就绪并且主要应该打印或 return 它给用户。如果队列中的第一个结果似乎是错误的 (None
),那么 main 应该等待队列中的第二个结果。如果 second 不错(不是 None
),那么它会被 return 发送给用户,否则两个 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!')