2012-05-15 28 views
3

希望這只是一個小小的我做錯了,因爲這些是我的一些使用隊列的第一個線程化腳本。基本上跑完後停下來坐在那裏,但不會退出。螺紋腳本停止結束後沒有關閉

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

所以,在這段代碼中,你要旋轉起來5個線程來處理隊列中的所有項目? –

回答

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

您正在使用的線程錯誤地在一對夫婦在你的代碼的方式:

首先,代碼似乎是在不正確的假設建造的一個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() 

它是使用異常有用在這裏,因爲否則隊列可能會清空,然後線程可能會嘗試從中取出,並且最終會永久等待添加項目。第三,在您的for循環中,您調用self.run(),它將控制傳遞給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()