【问题标题】:Raise unhandled exceptions in a thread in the main thread? [duplicate]在主线程的线程中引发未处理的异常? [复制]
【发布时间】:2010-12-23 16:15:09
【问题描述】:

有一些类似的问题,但没有一个提供我需要的答案。

如果我通过threading.Thread 创建线程,然后抛出未处理的异常,这些线程将被终止。我希望使用堆栈跟踪保留异常详细信息的默认打印,但也要降低整个过程。

我考虑过可以捕获线程中的所有异常,然后在主线程对象上重新引发它们,或者可以手动执行默认异常处理,然后在主线程。

最好的方法是什么?

【问题讨论】:

    标签: python exception-handling multithreading systemexit


    【解决方案1】:

    辅助线程可以在主线程中可靠地引发的唯一异常是KeyboardInterrupt:辅助线程执行此操作的方式是调用函数thread.interrupt_main()。无法将额外信息(关于异常原因)与引发的异常对象相关联——后者始终只是一个普通的KeyboardInterrupt。因此,您需要将该信息隐藏在其他地方,例如在Queue.Queue 的专用实例上——该信息可能包括辅助线程可以通过sys.exc_info() 获得的结果,当然还有您认为有用的任何其他内容。

    主线程将需要恢复那些额外的信息(并考虑到如果键盘中断实际上是由于用户按下 control-C 或类似的,那么队列将为空,因此,使用 get_nowait 并例如,准备处理Queue.Empty 异常),根据需要对其进行格式化,然后终止(如果所有辅助线程都是daemons,则整个进程在主线程终止时终止)。

    【讨论】:

    【解决方案2】:

    我写过关于Re-throwing exceptions in Python 的文章,其中包括非常类似的内容作为示例。

    在您的工作线程上执行此操作(Python 2.x,请参阅下面的 Python 3.x 版本):

    try:
        self.result = self.do_something_dangerous()
    except Exception, e:
        import sys
        self.exc_info = sys.exc_info()
    

    在你的主线程上你这样做:

    if self.exc_info:
        raise self.exc_info[1], None, self.exc_info[2]
    return self.result
    

    异常将出现在主线程中,就像它是在工作线程中引发的一样。

    Python 3.x:

    try:
        self.result = self.do_something_dangerous()
    except Exception as e:
        import sys
        self.exc_info = sys.exc_info()
    

    在你的主线程上:

    if self.exc_info:
        raise self.exc_info[1].with_traceback(self.exc_info[2])
    return self.result
    

    【讨论】:

    • 你不是说要在主线程中抛出thrdobj.exc_info吗,为什么在重新抛出的时候要丢掉异常类型?
    • 我现在看到了,必须阅读 3arg raise 声明。但是关于self的问题仍然存在,谢谢你的好答案,我会试试的
    • 我不确定您对 self 的问题是什么。此代码来自用于将工作推迟到工作线程的对象,因此同一对象在工作线程和主线程中运行代码。
    • 我怀疑问题不在于知道如何重新引发异常的机制,而在于何时重新引发异常,即主线程如何知道有等待重新引发的异常?
    • 这个答案stackoverflow.com/a/12223550 展示了一种将其封装到您的线程实现中的好方法,当它在工作线程上调用join() 时自动重新引发主线程中的异常。
    【解决方案3】:

    很遗憾,接受的答案没有回答问题。您宁愿将异常详细信息通过管道传输到队列中。请看:Catch a thread's exception in the caller thread in Python

    【讨论】:

      猜你喜欢
      • 2016-02-25
      • 2012-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-17
      • 2014-09-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多