当其中一个线程中存在未捕获的异常时,Python 多线程程序不会退出
Posted
技术标签:
【中文标题】当其中一个线程中存在未捕获的异常时,Python 多线程程序不会退出【英文标题】:Python multithreaded program does not exit when there is an uncaught exception in one of the threads 【发布时间】:2018-10-22 15:09:21 【问题描述】:下面的代码产生 100 个线程并随机生成一个异常。即使所有线程都已执行完毕(虽然有些线程会产生异常),但主程序仍然没有退出。难道我做错了什么?需要修改什么,以便如果其中一个线程发生异常,主线程仍然退出?
from __future__ import print_function
from threading import Thread
import sys
import random
from queue import Queue
__author__ = 'aanush'
"""
Testing if threading exits the python script gracefully
"""
class NoException(Exception):
pass
class ThreadFail(Thread):
"""
Class which helps us in doing multi-threading which improves performance of the script
"""
def __init__(self, name, counter, queue_):
Thread.__init__(self)
self.queue = queue_
self.threadID = counter
self.name = name
self.counter = counter
def run(self):
while True:
# Expand the tuple from queue and pass it to the target function
some_random_num = self.queue.get()
func_test(some_random_num)
self.queue.task_done()
def func_test(random_num):
if random_num <= 10:
print("Sleep time - greater than 10. Not raising exception".format(random_num))
else:
print('sleep time less than 10 : Raising exception')
raise NoException
queue = Queue()
for thread_num in range(100):
worker = ThreadFail('Thread-'.format(thread_num), thread_num, queue)
worker.daemon = True
worker.start()
for x in range(1000):
queue.put(random.randrange(1, 15))
queue.join()
【问题讨论】:
你能Ctrl+c吗?生成的堆栈跟踪可能会给您一个提示。 没有@progfan,即使 Ctrl+c 也不做任何事情。我必须使用“kill -9 pid”手动终止进程 我明白了。在第二次阅读之后,我意识到我没有准确地阅读你的问题。具体来说,我在您的run()
方法中没有看到while True
。 Darkanout 的回答是准确的,将有助于优雅地退出。话虽如此,奇怪的是您必须 kill
处理该过程并且 ctrl+C
不起作用; ctrl+c 对你的例子有用。
是的,问题是我正在使用 linux 中的 bash 脚本运行这个多线程程序,并在脚本失败时发送电子邮件(使用非零退出代码)。但是该过程处于挂起状态,并且每天都在没有电子邮件的情况下不断累积(因为脚本根本没有退出)。现在,Darkonaut 的这个解决方案帮助我纠正了这个问题。!
【参考方案1】:
您在这里遇到了僵局。由于异常而终止的线程不会释放共享资源上的持有锁,
因此queue
被破坏。您需要在线程内部捕获异常并让它们优雅地退出。
def run(self):
while True:
# Expand the tuple from queue and pass it to the target function
some_random_num = self.queue.get()
try:
func_test(some_random_num)
except NoException:
pass
finally:
self.queue.task_done()
【讨论】:
感谢@Darkonaut 的回复。这看起来很有帮助。我明天试试这个,然后告诉你。!以上是关于当其中一个线程中存在未捕获的异常时,Python 多线程程序不会退出的主要内容,如果未能解决你的问题,请参考以下文章