下面的Python程序启动一个线程,然后继续在主线程中执行操作。我将整个主线程包装在一个 try-except block 中,这样如果发生异常,我可以拆除所有正在运行的线程。
当我使用 Python 2.7.5 运行脚本并在程序执行期间的随机点调用 KeyboardInterrupt 时,会触发异常但未捕获异常。程序继续运行。
$ python test.py
Running server ...
Searching for servers ...
^CTraceback (most recent call last):
File "test.py", line 50, in <module>
main()
File "test.py", line 40, in main
app_main()
File "test.py", line 35, in app_main
searchservers()
File "test.py", line 26, in searchservers
time.sleep(0.0005)
KeyboardInterrupt
我错过了发生异常时在 main()
中打印的输出中的一行。
代码
import time
import threading
thread_pool = []
running = False
def stop():
global running
running = False
def runserver():
print "Running server ..."
global running
running = True
while running:
time.sleep(0.07)
def searchservers():
print "Searching for servers ..."
for i in xrange(256):
for j in xrange(256):
time.sleep(0.0005)
def app_main():
server = threading.Thread(target=runserver)
thread_pool.append(server)
server.start()
time.sleep(0.1)
searchservers()
stop()
def main():
try:
app_main()
except Exception as exc:
stop()
print "%s occured, joining all threads..." % exc.__class__.__name__
for thread in thread_pool:
thread.join()
raise exc
if __name__ == "__main__":
main()
为什么键盘中断没有被捕获?在线程程序中捕获异常并拆除整个过程的正确方法是什么?
最佳答案
KeyboardInterrupt
是一个特殊异常;与 MemoryError
、GeneratorExit
和 SystemExit
一样,它不是派生自基本 Exception
类。
因此,仅捕获异常
是不够的;你通常会明确地捕捉到它:
except (Exception, KeyboardInterrupt) as exc:
但是,您还 try catch 线程中的异常;线程有自己独立的堆栈;你不能只是去捕获主线程中那些堆栈中抛出的异常。您必须捕获该线程中的异常:
def runserver():
print "Running server ..."
global running
running = True
try:
while running:
time.sleep(0.07)
except (Exception, KeyboardInterrupt) as exc:
print "Error in the runserver thread"
要以通用方式处理此问题并将异常“传递”到主线程,您需要某种线程间通信。请参阅Catch a thread's exception in the caller thread in Python以获得完整的解决方案。
关于python - 无法捕获线程程序中的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19604943/