如果python中发生键盘异常,如何停止子线程?

时间:2019-09-03 09:50:20

标签: multithreading python-2.7 keyboardinterrupt

我面临线程概念的问题,即我有一个函数,该函数将创建10个线程来执行任务。如果发生键盘中断,那些创建的线程仍在执行,我想停止这些线程并恢复所做的更改。

以下代码sinppet是示例方法:

def store_to_db(self,keys_size,master_key,action_flag,key_status):
    for iteration in range(10):
        t = threading.Thread(target=self.store_worker, args=())
        t.start()
        threads.append(t)
    for t in threads:
        t.join()

def store_worker():
    print "DOING"

1 个答案:

答案 0 :(得分:0)

实现此目的的想法是:

  • 您需要一个“线程池”,用于检查线程的do_run属性是否为虚假。
  • 您需要在该池外创建一个“前哨线程”,以检查池中的线程状态并根据需要调整“线程池”线程的do_run属性。

示例代码:

import threading
import random
import time
import msvcrt as ms


def main_logic():
    # take 10 worker threads
    threads = []
    for i in range(10):
        t = threading.Thread(target=lengthy_process_with_brake, args=(i,))
        # start and append
        t.start()
        threads.append(t)

    # start the thread which allows you to stop all threads defined above
    s = threading.Thread(target=sentinel, args=(threads,))
    s.start()

    # join worker threads
    for t in threads:
        t.join()


def sentinel(threads):
    # this one runs until threads defined in "threads" are running or keyboard is pressed
    while True:
        # number of threads are running
        running = [x for x in threads if x.isAlive()]

        # if kb is pressed
        if ms.kbhit():
            # tell threads to stop
            for t in running:
                t.do_run = False
        # if all threads stopped, exit the loop
        if not running:
            break

        # you don't want a high cpu load for nothing
        time.sleep(0.05)


def lengthy_process_with_brake(worker_id):
    # grab current thread
    t = threading.currentThread()

    # start msg
    print(f"{worker_id} STARTED")

    # exit condition
    zzz = random.random() * 20
    stop_time = time.time() + zzz

    # imagine an iteration here like "for item in items:"  
    while time.time() < stop_time:

        # the brake
        if not getattr(t, "do_run", True):
            print(f"{worker_id} IS ESCAPING")
            return

        # the task
        time.sleep(0.03)

    # exit msg
    print(f"{worker_id} DONE")

    # exit msg
    print(f"{worker_id} DONE")



main_logic()

此解决方案不会“杀死”线程,只是告诉他们停止迭代或执行任何操作。

编辑: 我只是注意到标题中有“键盘异常”,而不是“任何键”。键盘异常处理有些不同,here is a good solution与此不同。关键点几乎是相同的:您告诉线程是否满足条件。

相关问题