thread.start_new_thread:将异常转移到主线程

时间:2013-01-14 09:47:03

标签: python

  

可能重复:
  Catch a thread’s exception in the caller thread in Python

我有一个给定的代码,并且有一个

thread.start_new_thread()

正如我刚才读到的python doc:“当函数以未处理的异常终止时,会打印一个堆栈跟踪,然后线程退出(但其他线程继续运行)。” 但是当(新)函数以异常终止时我想终止主线程 - 所以异常应该转移到主线程。我怎么能这样做?

编辑: 这是我的代码的一部分:

def CaptureRegionAsync(region=SCREEN, name="Region", asyncDelay=None, subDir="de"):
    if asyncDelay is None:
        CaptureRegion(region, name, subDir)
    else:
        thread.start_new_thread(_CaptureRegionAsync, (region, name, asyncDelay, subDir))

def _CaptureRegionAsync(region, name, asyncDelay, subDir):
    time.sleep(max(0, asyncDelay))
    CaptureRegion(region, name, subDir)

def CaptureRegion(region=SCREEN, name="Region", subDir="de"):
    ...
    if found:
        return
    else:
        raise Exception(u"[warn] Screenshot has changed: %s" % filename)

CaptureRegionAsync(myregion,"name",2)

1 个答案:

答案 0 :(得分:0)

UPD:这不是最佳解决方案,因为您的问题与我的想法不同:我希望您尝试处理无法修改的线程代码中的异常。但是,我决定不删除答案。

很难从另一个线程中捕获异常。通常应该手动转移。

你能包装一个线程函数吗?如果你将崩溃的工作线程包装成try ...除外,那么你可以执行退出except块中的主线程所需的操作(sys.exit似乎没用,虽然这对我来说很意外,但是有thread.interrupt_main()os.abort(),但你可能需要一些更优雅的东西,比如设置主要线程定期检查的标志。)

但是,如果您无法包装该函数(无法修改调用start_new_thread的第三方代码),您可以尝试猴子修补线程模块(或第三方模块本身)。修补版start_new_thread()应该包含你担心的函数:

import thread
import sys
import time

def t():
    print "Thread started"
    raise Exception("t Kaboom")

def t1():
    print "Thread started"
    raise Exception("t1 Kaboom")


def decorate(s_n_t):
    def decorated(f, a, kw={}):
        if f != t:
            return s_n_t(f, a, kw)
        def thunk(*args, **kwargs):
            try:
                f(*args, **kwargs)
            except:
                print "Kaboom"
                thread.interrupt_main() # or os.abort()
        return s_n_t(thunk, a, kw)
    return decorated

# Now let's do monkey patching:
thread.start_new_thread = decorate(thread.start_new_thread)

thread.start_new_thread(t1, ())
time.sleep(5)
thread.start_new_thread(t, ())
time.sleep(5)

此处t()中的例外导致thread.interrupt_main() / os.abort()。应用程序中的其他线程函数不受影响。