Python 线程脚本在结束后停止而不关闭

Python 线程脚本在结束后停止而不关闭,python,multithreading,queue,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):

希望这只是我做错的小事情,因为这是我第一次使用队列的线程脚本。基本上,跑完之后,它会停下来,坐在那里,但不会退出

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()

在我看来,当你真的需要一个简单的解决方案时,你把线程的许多不同方面都混在了一起。据我所知,范围(5):中I的
循环永远不会通过第一次迭代,因为您运行线程,它会陷入无限循环中

我会这样做:

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()

您在代码中以几种方式错误地使用了线程:

首先,代码似乎建立在一个错误的假设之上,即您拥有的
Thread
子类对象可以生成完成工作所需的所有线程。相反,表示每个
线程
对象最多只能调用一次
start
。对于
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()
在这里使用异常是很有用的,因为否则队列可能会清空,然后线程可能会尝试从中获取,它将永远等待添加项

第三,在for循环中调用
self.run()
,它将控制权传递给
run
方法,然后该方法处理整个队列,并在方法更改为终止后返回
None
。以下行将抛出异常,因为
t
将被分配值
None
。由于您希望生成其他线程来执行此工作,因此应该执行
t=Word(queue)
以获取新的Word线程,然后执行
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()

如果您想阅读Python中的一些线程代码示例,下面的方法可能会教您一些关于这个主题的基础知识。其中一些是演示,另一些是程序:


在这段代码中,您试图启动5个线程来处理队列中的所有项目?