1

可能重复:
在 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)
4

1 回答 1

0

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

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

你能包装一个线程函数吗?如果您将崩溃的工作线程包装到 try...except 中,那么您可能会执行退出主线程所需的操作except块(sys.exit似乎没用,虽然这让我感到惊讶,但是有thread.interrupt_main()and 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()。应用程序中的其他线程函数不受影响。

于 2013-01-14T10:11:47.843 回答