我在这里尝试做的是使用键盘中断退出程序中所有正在进行的线程。这是我创建线程的代码的简化版本:
for i in taskDictionary:
try:
sleep(60)
thread = Thread(target = mainModule.executeThread)
thread.start()
except KeyboardInterrupt:
thread.__stop()
程序本身要复杂得多,占据了影响线程的大量不同变量,甚至可以选择以顺序模式启动,其中任务没有线程化,而是逐个启动,所以可能会我刚刚想到这个小变化的一些问题。 我以产生50/50结果的方式完成了这项工作。中断可以工作,但线程永远不会干净地退出。有时它们会继续运行但是停止执行未来的线程,有时候它们会因为中断的大量错误而退出,有时中断根本不会执行任何操作。上次我运行它时,程序停止执行任何未来的线程,但没有停止当前线程。 有没有办法退出线程而不进入线程实际执行的模块?
答案 0 :(得分:54)
类似的问题是“你如何杀死一个线程?”
您在线程中创建一个退出处理程序,该处理程序由来自线程模块的锁定或事件对象控制。然后,您只需删除锁定或发出事件对象的信号。这通知线程它应该停止处理并优雅地退出。在主程序中发出线程信号后,剩下要做的就是在thread.join()
中使用main
方法,等待线程关闭。
一个简短的例子:
import threading
import time
def timed_output(name, delay, run_event):
while run_event.is_set():
time.sleep(delay)
print name,": New Message!"
def main():
run_event = threading.Event()
run_event.set()
d1 = 1
t1 = threading.Thread(target = timed_output, args = ("bob",d1,run_event))
d2 = 2
t2 = threading.Thread(target = timed_output, args = ("paul",d2,run_event))
t1.start()
time.sleep(.5)
t2.start()
try:
while 1:
time.sleep(.1)
except KeyboardInterrupt:
print "attempting to close threads. Max wait =",max(d1,d2)
run_event.clear()
t1.join()
t2.join()
print "threads successfully closed"
if __name__ == '__main__':
main()
如果您真的需要 kill 线程的功能,请使用多处理。它允许您将SIGTERM发送到单个“进程”(它也与线程模块非常相似)。一般来说,线程适用于IO绑定时,多处理适用于您真正受处理器限制的情况。
答案 1 :(得分:1)
有两个选项不需要在线程之间使用锁或其他信号。一种是将线程设置为daemons,这将在主线程退出时自动终止。另一种方法是使用processes,如果需要杀死它们并保持主程序运行,则可以从主进程调用终止方法。
如果您的线程阻塞了输入,则这两个选项特别有用。在大多数情况下,使用超时并定期检查信号在大多数情况下都可以正常工作,而使用守护程序或进程则不需要任何繁忙的循环或显着增加的复杂性。
有关这些解决方案的更多详细信息和有关杀死线程问题的讨论,请参见this question的答案。