用键盘中断关闭所有线程

Joe*_*Joe 37 python multithreading

我在这里尝试做的是使用键盘中断退出程序中所有正在进行的线程.这是我的代码的简化版本,其中创建了线程:

for i in taskDictionary:
    try:
        sleep(60)
        thread = Thread(target = mainModule.executeThread)
        thread.start()
    except KeyboardInterrupt:
        thread.__stop()
Run Code Online (Sandbox Code Playgroud)

程序本身要复杂得多,占据了影响线程的大量不同变量,甚至可以选择以顺序模式启动,其中任务没有线程化,而是逐个启动,因此可能存在一些问题我只是想起了这个小小的变化.我以产生50/50结果的方式完成了这项工作.中断可以工作,但线程永远不会干净地退出.有时它们会继续运行但是停止执行未来的线程,有时候它们会因为中断的大量错误而退出,有时中断根本不会执行任何操作.上次我运行它时,程序停止执行任何未来的线程,但没有停止当前线程.有没有办法退出线程而不进入线程实际执行的模块?

Pau*_*eeb 56

一个类似的问题是"你如何杀死一个线程?"

您在线程中创建一个退出处理程序,该处理程序由来自线程模块的锁或事件对象控制.然后,您只需删除锁定或发出事件对象的信号.这通知线程它应该停止处理并优雅地退出.在你的主程序信号线后,剩下要做的唯一事情是使用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()
Run Code Online (Sandbox Code Playgroud)

如果您真的需要杀死线程的功能,请使用多处理.它允许您将SIGTERM发送到单个"进程"(它也与线程模块非常相似).一般来说,线程适用于IO绑定时,多处理适用于您真正受处理器限制的情况.

  • 通过线程的合作,您可以以任何方式杀死它.没有线程的合作,没有安全的方法来做到这一点,所有的道路都会导致痛苦. (8认同)
  • 精彩回答!不完全是我正在寻找但足够广泛,我能够将逻辑调整到我需要的东西!感谢那! (2认同)
  • @Dylan 无限循环只是为了提供一个简洁的工作示例。通常,人们会在主循环中完成一些主要任务。尽管如此,即使是 `time.sleep(.001)` 也应该显着减少 CPU 负载。在 `time.sleep(.010)` 时,我的 python 线程运行时 CPU 利用率不到 1%。线程应该用于 IO 绑定进程或需要定期检查的资源。主循环应该执行您的主要代码,如果它需要资源,可能可以休眠 50 毫秒来等待。如果处理确实对时间敏感,您始终可以使用“锁定”协议来睡眠和唤醒。 (2认同)

小智 6

有几个选项不需要在线程之间使用锁或其他信号。一是将线程设置为守护进程,当主线程退出时,守护进程会自动终止。另一种是使用进程,如果您需要终止它们并保持主程序运行,您可以从主进程调用终止方法。

如果线程在输入上阻塞,这两种方法都特别有用。虽然使用超时和定期检查信号在大多数情况下都可以工作而不会产生太多开销,但使用守护程序或进程消除了对任何繁忙循环或显着增加的复杂性的需要。

有关这些解决方案的更多详细信息以及有关终止线程问题的讨论,请参阅此问题的答案。