【问题标题】:thread.start_new_thread: transfer exception to main-thread [duplicate]thread.start_new_thread:将异常转移到主线程[重复]
【发布时间】:2012-12-28 06:34:17
【问题描述】:

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

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

thread.start_new_thread()

正如我刚刚在 python 文档中读到的:“当函数因未处理的异常而终止时,会打印堆栈跟踪,然后线程退出(但其他线程继续运行)。” 但是当(新)函数因异常而终止时,我也想终止主线程-因此应将异常转移到主线程。我该怎么做?

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

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)

【问题讨论】:

  • 对我来说似乎是另一个问题,而不是重复。如果“给定代码”是指“无法修改的第三方代码”,问题就完全不同了。
  • 对不起,“给定的代码”表示不是我写的,所以我不是很熟悉——但我可以修改它。
  • 那么我的第一个答案不是你的问题,猴子修补线程是个坏主意。 :-)

标签: python


【解决方案1】:

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

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

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

【讨论】:

  • 感谢您的回答! new_thread 中的 sys.exit() 不会杀死主线程:“sys.exit() [...] 只会在从主线程 [...] 调用时退出进程” (docs.python.org/2/library/sys.html)所以它对我不起作用。我编辑了我的第一篇文章并添加了一部分代码。
  • 哇...真的,它本身引发了一个异常...
  • 修复它以使用 thread.interrupt_main()
猜你喜欢
  • 2017-01-11
  • 2013-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-17
  • 2015-06-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多