线程脚本在结束后停止而没有关闭

时间:2012-05-15 16:50:11

标签: python multithreading queue

希望这只是一些小错误,因为这些是我使用队列的第一个线程脚本。基本上经过它后停下来坐在那里但不会退出。

import threading
import Queue
class Words(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.queue = Queue.Queue()     

    def word(self):
        read = open('words.txt')
        for word in read:
            word = word.replace("\n","")
            self.queue.put(word)       
        read.close() 
        for i in range(5):
            t = self.run()
            t.setDaemon(True)
            t.start()  
        self.queue.join()

    def run(self): 
        while True:
            word = self.queue.get()
            print word 
            self.queue.task_done()

    if __name__ == '__main__':
        Word =  Words()
        Word.word()

3 个答案:

答案 0 :(得分:2)

您在代码中以不同方式错误地使用线程:

首先,代码似乎建立在不正确的假设之上,即你拥有的一个Thread子类对象可以产生你需要完成工作的所有线程。相反,Thread documentation表示每个start对象最多只能调用Thread“一次。对于word方法,这是self引用。

但是,调用self.start()是没有用的,因为这会产生一个线程来消耗队列,并且你不会从线程中获得任何东西。由于word无论如何都必须构造Words的新实例来启动多个线程,并且需要多个Words实例访问队列对象,因此同时使用两个Words实例都是有用的。那些与word对象分开的。例如,Words可以是def word(): queue = Queue.Queue() read = open('words.txt') for word in read: word = word.replace("\n","") self.put(word) read.close() #... 对象之外的函数,它起始于:

Words

这也意味着class Words(threading.Thread): def __init__(self, queue): threading.Thread.__init__(self) self.queue = queue 必须将队列对象作为参数,以便多个实例共享同一个队列:

run

其次,你的线程函数(def run(self): while True: try: word = self.queue.get(False) except Queue.Empty: break print word self.queue.task_done() )是一个无限循环,所以线程永远不会终止。由于在将所有项目添加到队列后只运行队列使用者线程,因此在队列为空时终止线程应该没有问题,如下所示:

self.run()

在这里使用异常非常有用,因为否则队列可能会清空,然后线程可能会尝试从中获取,并且最终会等待一个项目被添加。

第三,在你的for循环中调用run,它将控制传递给None方法,然后该方法处理整个队列并在方法更改为终止后返回t。以下行将抛出异常,因为None将被赋值t = Word(queue)。由于您希望生成其他线程来完成工作,因此您应该t.start()获取新的单词线程,然后class Words(threading.Thread): def __init__(self, queue): threading.Thread.__init__(self) self.queue = queue def run(self): while True: try: word = self.queue.get(False) except Queue.Empty: break print word self.queue.task_done() def word(): queue = Queue.Queue() read = open('words.txt') for word in read: word = word.replace("\n","") self.put(word) read.close() for i in range(5): t = Word() t.setDaemon(True) t.start() queue.join() if __name__=='__main__': word() 开始。所以,放在一起的代码应该是

{{1}}

答案 1 :(得分:0)

当我真正需要一个简单的解决方案时,我认为你正在混合线程的许多不同方面。据我所知,for i in range(5):循环永远不会超过第一次迭代,因为你运行线程并且它被无限循环捕获。

我将如何做到这一点:

import threading
import Queue

class Worker(threading.Thread):
    def __init__(self, queue):
        threading.Thread.__init__(self)
        self.queue = queue

    def run(self):
        while True:
            # try to dequeue a word from the queue
            try:
                word = self.queue.get_nowait()
            # if there's nothing in the queue, break because we're done
            except Queue.Empty:
                break

            # if the 'try' was successful at getting a word, print it
            print word


def fill_queue(queue):
    read = open('words.txt')
    for word in read:
        word = word.replace("\n", "")
        queue.put(word)
    read.close()


if __name__ == "__main__":
    # create empty queue
    queue = Queue.Queue()

    # fill the queue with work
    fill_queue(queue)

    # create 5 worker threads
    threads = []
    for i in range(5):
        threads.append(Worker(queue))

    # start threads
    for thread in threads:
        thread.start()

    # join threads once they finish
    for thread in threads:
        thread.join()

答案 2 :(得分:0)

如果您想阅读Python中的一些线程代码示例,以下配方可能会教您一些有关该主题的基础知识。其中一些是演示,其他是节目: