2013-09-28 53 views
7

我試圖爲了我自己的目的實現這個多處理tutorial。起初我認爲它不能很好地擴展,但是當我做出一個可重複的例子時,我發現如果項目列表超過124,它似乎永遠不會返回答案。在x = 124它運行在0.4秒,但是當我將它設置爲x = 125它永遠不會結束。我在Windows 7上運行Python 2.7。Python多處理> = 125列表永遠不會完成

from multiprocessing import Lock, Process, Queue, current_process 
import time 

class Testclass(object): 
    def __init__(self, x): 
     self.x = x 

def toyfunction(testclass): 
    testclass.product = testclass.x * testclass.x 
    return testclass 


def worker(work_queue, done_queue): 
    try: 
     for testclass in iter(work_queue.get, 'STOP'): 
      print(testclass.counter) 
      newtestclass = toyfunction(testclass) 
      done_queue.put(newtestclass) 

    except: 
     print('error') 

    return True 

def main(x): 

    counter = 1 

    database = [] 
    while counter <= x: 
     database.append(Testclass(10)) 
     counter += 1 
     print(counter) 



    workers = 8 
    work_queue = Queue() 
    done_queue = Queue() 
    processes = [] 

    start = time.clock() 
    counter = 1 

    for testclass in database: 
     testclass.counter = counter 
     work_queue.put(testclass) 
     counter += 1 
     print(counter) 


    print('items loaded') 
    for w in range(workers): 
     p = Process(target=worker, args=(work_queue, done_queue)) 
     p.start() 
     processes.append(p) 
     work_queue.put('STOP') 

    for p in processes: 
     p.join() 

    done_queue.put('STOP') 

    newdatabase = [] 
    for testclass in iter(done_queue.get, 'STOP'): 
     newdatabase.append(testclass) 

    print(time.clock()-start) 
    print("Done") 
    return(newdatabase) 

if __name__ == '__main__': 
    database = main(124) 
    database2 = main(125) 
+0

它適合我。 – Veedrac

+0

他在這裏發佈了另一個對我有效的問題。 http://stackoverflow.com/questions/19070638/python-multiprocessing-ioerror-errno-232-the-pipe-is-being-closed#comment28188856_19070638 –

+0

我解決了另一篇文章中的問題。我試過在兩臺計算機上運行上面的代碼,並且它在'x = 125'結束時掛起,並且從不打印完成。 – Michael

回答

6

行!從the docs

警告正如上面提到的,如果一個子進程已經把項目一個隊列(它有使用JoinableQueue.cancel_join_thread不 ),那麼該過程將不會終止,直到所有 緩衝項目已被刷新到管道。 這意味着如果您嘗試加入該進程,您可能會遇到死鎖,除非您確定 已放入隊列的所有項目都已被使用。同樣,如果 子進程是非守護進程,那麼當父進程嘗試 加入其所有非守護進程子進程時,父進程可能會在退出時掛起。請注意,使用管理器創建的隊列確實不存在此問題 。請參閱編程準則。

正如我在評論前面提到的,代碼嘗試.join()過程done_queue隊列排出 - 而改變代碼中一個時髦的辦法,以確保後done_queue.join()之前「荷蘭國際集團倒掉,該代碼可以很好地處理一百萬個項目。

所以這是一個飛行員錯誤的情況,雖然很模糊。至於爲什麼行爲取決於傳遞給main(x)的數字,這是不可預知的:這取決於內部如何完成緩衝。這樣的樂趣;-)

+0

您是否建議針對上述代碼的任何特定工作?人們通常會從隊列中取回成品嗎? – Michael

+3

我已經在註釋中解釋過我如何「修復」這個:在工作結束之前更改'worker()'完成'done_queue.put('STOP')'。改變主程序在'done_queue'上的迭代來計算它看到'STOP'的次數 - 當它看到它們的'workers'時就完成了。在'done_queue'上的迭代完成後,移動'.join()'**。 –