如何终止一个多线程python程序?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (696)

如何使多线程python程序响应Ctrl+C键事件?

代码如下:

import threading
current = 0

class MyThread(threading.Thread):
    def __init__(self, total):
        threading.Thread.__init__(self)
        self.total = total

    def stop(self):
        self._Thread__stop()

    def run(self):
        global current
        while current<self.total:
            lock = threading.Lock()
            lock.acquire()
            current+=1
            lock.release()
            print current

if __name__=='__main__':

    threads = []
    thread_count = 10
    total = 10000
    for i in range(0, thread_count):
        t = MyThread(total)
        t.setDaemon(True)
        threads.append(t)
    for i in range(0, thread_count):
        threads[i].start()

我试图删除所有线程上的join(),但它仍然不起作用。是否因为每个线程的run()过程中的锁段?

上面的代码应该可以工作,但是当当前变量在5,000-6,000范围内并且通过如下错误时它总是中断

Exception in thread Thread-4 (most likely raised during interpreter shutdown):
Traceback (most recent call last):
  File "/usr/lib/python2.5/threading.py", line 486, in __bootstrap_inner
  File "test.py", line 20, in run
<type 'exceptions.TypeError'>: unsupported operand type(s) for +=: 'NoneType' and 'int'
Exception in thread Thread-2 (most likely raised during interpreter shutdown):
Traceback (most recent call last):
  File "/usr/lib/python2.5/threading.py", line 486, in __bootstrap_inner
  File "test.py", line 22, in run
提问于
用户回答回答于

除了主线程之外,每个线程都是一个守护进程(t.daemon = True在启动之前t.setDaemon(True),每个线程对象的t优先级为2.6或更低,2.6或更低)。这样,当主线程收到KeyboardInterrupt时,如果它没有捕获它或捕获它,但决定终止,整个过程将终止。看文档

看到OP的代码(并非最初发布)和声称“它不工作”,它似乎我必须添加:

当然,如果你希望你的主线程保持响应(如控制-C),不阻塞调用,如join荷兰国际集团另一个线程-尤其是没有完全无用的阻塞调用,如join荷兰国际集团守护线程。例如,只需从当前(无声和破坏性)主线程中更改最后一个循环:

for i in range(0, thread_count):
    threads[i].join()

一些更明智的事情,比如:

while threading.active_count() > 0:
    time.sleep(0.1)

如果Main没有什么更好的事情要做,那么要么所有线程自行终止,要么接收控件-C(或其他信号)。

当然,如果希望线程不像守护线程那样突然终止,那么还有许多其他可用的模式--除非他们同样,也永远陷入无条件的阻塞调用、死锁之类的困境。

用户回答回答于

有两种主要方式,一种是干净的,一种是简单的。

干净的方法是在主线程中捕获KeyboardInterrupt,并设置一个标志,让后台线程可以检查以便知道退出; 这是一个简单/稍微凌乱的版本,使用全局:

exitapp = False
if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        exitapp = True
        raise

def threadCode(...):
    while not exitapp:
        # do work here, watch for exitapp to be True

混乱但简单的方法是捕获KeyboardInterrupt并调用os._exit(),它立即终止所有线程。

扫码关注云+社区

领取腾讯云代金券