如何在Python中使用队列处理线程中的异常?

时间:2014-08-08 09:26:22

标签: python multithreading queue

永远不会打印: " threadfuncqueue"处理的threadfuncqueue中的异常, "主线程处理的threadfuncqueue中的异常"和 "队列传递的线程测试"。永不放弃!

from threading import Thread
from Queue import Queue
import time

class ImRaiseError():
    def __init__(self):
        time.sleep(1)
        raise Exception(self.__class__.__name__)

# place for paste worked code example from below 

print "begin thread test with queue"
def threadfuncqueue(q):
    print "\n"+str(q.get())
    while not q.empty():
        try:
            testthread = ImRaiseError()
        finally:
            print "Exception in threadfuncqueue handled by threadfuncqueue"

q = Queue()
items = [1,2]
for i in range(len(items)):
     t = Thread(target=threadfuncqueue,args=(q,))
     if(1 == i):
        t.daemon = False
     else:
        t.daemon = True
     t.start()
for item in items:
    q.put("threadfuncqueue"+str(item))

try:
    q.join()       # block until all tasks are done
finally:
    print "Exception in threadfuncqueue handled by main thread"
print "thread test with queue passed"
quit()

如何处理此异常?

工作代码示例,但没有队列:

print "=========== procedure style test"
def threadfunc(q):
    print "\n"+str(q)
    while True:
        try:
            testthread = ImRaiseError()
        finally:
            print str(q)+" handled by process"

try:
    threadfunc('testproc')
except Exception as e:
    print "error!",e
print "procedure style test ==========="


print "=========== simple thread tests"
testthread = Thread(target=threadfunc,args=('testthread',))
testthread.start()
try:
    testthread.join()
finally:
    print "Exception in testthread handled by main thread"
testthread1 = Thread(target=threadfunc,args=('testthread1',))
testthread1.start()
try:
    testthread1.join()
finally:
    print "Exception in testthread1 handled by main thread"
print "simple thread tests ==========="

1 个答案:

答案 0 :(得分:2)

简答

您正在将事物放入队列并检索它们,但如果您要加入队列,则需要将任务标记为已完成,然后将它们从队列中拉出并处理它们。 According to the docs,每次将项目排入队列时,计数器都会递增,您需要调用q.task_done()来递减该计数器。 q.join()将阻止,直到该计数器达到零。在q.get()通话后立即添加此功能,以防止主被阻止:

q.task_done()

此外,我发现您在中检索到某些内容之后,正在检查q空虚,这很奇怪。我不确定你到底想要实现什么,所以我没有给你任何建议,但我建议你重新考虑你在那个领域的设计。

其他想法

一旦你使这段代码工作,你应该把它转移到Code Review因为它有点混乱。以下是您的一些想法:

异常处理

您实际上并没有“处理”threadfuncqueue(q)中的例外情况。所有finally语句都允许您在发生异常时执行清理代码。它实际上并没有捕获和处理异常。异常仍然会在调用堆栈中向上移动。考虑这个例子,test.py:

try:
    raise Exception
finally:
    print("Yup!")
print("Nope!")

输出:

  

烨!
  追溯(最近的呼叫最后):
  文件“test.py”,第2行,在   提出异常
  例外

注意“是的!”打印时“不!”没有。 finally块中的代码已执行,但这并未阻止异常向上传播并停止解释器。您需要except语句:

try:
    raise Exception
except Exception: # only catch the exceptions you expect
    print("Yup!")
print("Nope!")

输出:

  

烨!
  都能跟得上!

这次都印刷了,因为我们抓住并处理了例外。

异常提升

您当前在线程中引发异常的方法是不必要的复杂。不要创建整个ImRaiseError类,只需使用字符串提出所需的异常:

raise Exception('Whatever error message I want')

如果您发现自己手动操纵mangled names(例如self.__class__.__name__),那么您通常会做错事。

额外圆括号

在Python中通常不喜欢使用条件表达式的括号:

if(1 == i): # unnecessary extra characters 

尝试打破C / C ++ / Java习惯并摆脱它们:

if 1 == i:

其他

我已经超出了这个问题的范围,所以我现在要解决这个问题,但是还有一些其他的事情你可以清理并且更加惯用。当你在这里完成时,请转到Code Review,看看还有什么可以改进。