当前位置:  开发笔记 > 编程语言 > 正文

终止多线程python程序

如何解决《终止多线程python程序》经验,为你挑选了3个好方法。

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

编辑:代码是这样的:

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

我试图在所有线程上删除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
: 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

Alex Martell.. 91

除了主线程之外的每个线程都是一个守护进程(t.daemon = True2.6或更好,t.setDaemon(True)在2.6或更少,对于每个线程对象,t然后再启动它).这样,当主线程接收到KeyboardInterrupt时,如果它没有捕获它或捕获它但决定终止,整个过程将终止.查看文档.

编辑:刚刚看到OP的代码(最初没有发布)和"它不起作用"的说法,似乎我必须添加...:

当然,如果你希望你的主线程保持响应(例如控制-c),不要让它陷入阻塞调用,例如join另一个线程 - 尤其不是完全无用的阻塞调用,例如joining 守护程序线程.例如,只需从当前更改主线程中的最后一个循环(无语和破坏):

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

更合理的事情:

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

如果你的主要没有比所有线程自己终止,或者接收控制-C(或其他信号)更好的事情.

当然,还有许多其他可用的模式,如果你宁愿让你的线程没有突然终止(作为守护线程) - 除非他们也永远陷入无条件阻塞调用,死锁等等;-) .



1> Alex Martell..:

除了主线程之外的每个线程都是一个守护进程(t.daemon = True2.6或更好,t.setDaemon(True)在2.6或更少,对于每个线程对象,t然后再启动它).这样,当主线程接收到KeyboardInterrupt时,如果它没有捕获它或捕获它但决定终止,整个过程将终止.查看文档.

编辑:刚刚看到OP的代码(最初没有发布)和"它不起作用"的说法,似乎我必须添加...:

当然,如果你希望你的主线程保持响应(例如控制-c),不要让它陷入阻塞调用,例如join另一个线程 - 尤其不是完全无用的阻塞调用,例如joining 守护程序线程.例如,只需从当前更改主线程中的最后一个循环(无语和破坏):

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

更合理的事情:

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

如果你的主要没有比所有线程自己终止,或者接收控制-C(或其他信号)更好的事情.

当然,还有许多其他可用的模式,如果你宁愿让你的线程没有突然终止(作为守护线程) - 除非他们也永远陷入无条件阻塞调用,死锁等等;-) .


@jack,你现在给出的代码立即终止(当然,因为主线程"落到了最后"并且结束了一切).所以它不能完全接近你实际尝试的内容,很明显你甚至没有尝试过你发布的代码; 让你很难帮助你!请发布您尝试过的代码,并重现您遇到的问题,这样我就可以向您展示您的错误在该代码中的位置,而不是试图猜测您看不见的代码可能具有的错误.
@jack,正如我已经提到过的,如果那是你的代码,那么现在你的主要错误就是"主线程"从最终落下"并结束了一切".试试我上面给出的代码:`while threading.active_count()> 0:time.sleep(0.1)` - 为什么让我重复这个?!你可以做得更好(线程中的'while`应该`和`一个全局标志,以便它可以干净地停止)但是你有一些可怕的错误首先要修复:它们包括一个锁定的获取/释放,这是一个新的局部变量,这与没有锁定相同,而不是所有线程共享的锁.

2> Walter Mundt..:

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

干净的方法是在你的主线程中捕获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(),它会立即终止所有线程.


谢谢,注意:它是python3.x中的os._exit(0)

3> 小智..:

一个工人可能对你有所帮助:

#!/usr/bin/env python

import sys, time
from threading import *
from collections import deque

class Worker(object):
    def __init__(self, concurrent=1):
        self.concurrent = concurrent
        self.queue = deque([])
        self.threads = []
        self.keep_interrupt = False

    def _retain_threads(self):
        while len(self.threads) < self.concurrent:
            t = Thread(target=self._run, args=[self])
            t.setDaemon(True)
            t.start()
            self.threads.append(t)


    def _run(self, *args):
        while self.queue and not self.keep_interrupt:
            func, args, kargs = self.queue.popleft()
            func(*args, **kargs)

    def add_task(self, func, *args, **kargs):
        self.queue.append((func, args, kargs))

    def start(self, block=False):
        self._retain_threads()

        if block:
            try:
                while self.threads:
                    self.threads = [t.join(1) or t for t in self.threads if t.isAlive()]
                    if self.queue:
                        self._retain_threads()
            except KeyboardInterrupt:
                self.keep_interrupt = True
                print "alive threads: %d; outstanding tasks: %d" % (len(self.threads), len(self.queue))
                print "terminating..."


# example
print "starting..."
worker = Worker(concurrent=50)

def do_work():
    print "item %d done." % len(items)
    time.sleep(3)

def main():
    for i in xrange(1000):
        worker.add_task(do_work)
    worker.start(True)

main()
print "done."

# to keep shell alive
sys.stdin.readlines()

推荐阅读
周扒pi
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有