sys.excepthook' 与线程处理
我正在使用Python 2.5,并尝试在我的程序中使用自己定义的excepthook
。在主线程中,它工作得很好。但是在使用线程模块启动的线程中,通常的excepthook
会被调用。
这里有一个例子展示了这个问题。取消注释后就能看到想要的效果。
import threading, sys
def myexcepthook(type, value, tb):
print 'myexcepthook'
class A(threading.Thread, object):
def __init__(self):
threading.Thread.__init__(self, verbose=True)
# raise Exception('in main')
self.start()
def run(self):
print 'A'
raise Exception('in thread')
if __name__ == "__main__":
sys.excepthook = myexcepthook
A()
那么,我该如何在一个线程中使用我自己的excepthook
呢?
3 个回答
13
看起来这里有一个相关的错误报告,详细内容可以在这里找到,里面还有一些解决方法。建议的做法基本上是在运行代码时加上一个“尝试/捕获”的结构,然后调用 sys.excepthook(*sys.exc_info())
来处理错误。
23
看起来这个问题在(至少)3.4版本中仍然存在,而Nadia Alramli提到的讨论中的一个解决方法在Python 3.4中似乎也有效。
为了方便大家和记录下来,我在这里分享我认为最好的解决方法的代码。我稍微更新了一下代码风格和注释,使其更符合PEP8标准和Python的风格。
import sys
import threading
def setup_thread_excepthook():
"""
Workaround for `sys.excepthook` thread bug from:
http://bugs.python.org/issue1230540
Call once from the main thread before creating any threads.
"""
init_original = threading.Thread.__init__
def init(self, *args, **kwargs):
init_original(self, *args, **kwargs)
run_original = self.run
def run_with_except_hook(*args2, **kwargs2):
try:
run_original(*args2, **kwargs2)
except Exception:
sys.excepthook(*sys.exc_info())
self.run = run_with_except_hook
threading.Thread.__init__ = init
29
我刚遇到这个问题,结果发现这正是个好时机。
在3.8版本中新增了: threading.excepthook
这个功能用来处理线程运行时出现的未捕获异常。
它的参数有以下几个属性:
exc_type: 异常的类型。
exc_value: 异常的值,可以是None。
exc_traceback: 异常的追踪信息,可以是None。
thread: 抛出异常的线程,可以是None。
我不知道为什么,但要注意,和 sys.excepthook
不同的是, threading.excepthook
接收的参数是以 namedtuple
的形式,而不是多个单独的参数。