2016-11-18 41 views
3

不處理名單我有這樣的腳本來處理某些URL並行:多pool.map爲了

import multiprocessing 
import time 

list_of_urls = [] 

for i in range(1,1000): 
    list_of_urls.append('http://example.com/page=' + str(i)) 

def process_url(url): 
    page_processed = url.split('=')[1] 
    print 'Processing page %s'% page_processed 
    time.sleep(5) 

pool = multiprocessing.Pool(processes=4) 
pool.map(process_url, list_of_urls) 

列表是有序的,但是當我運行它,該腳本不挑從網址列表爲了:

Processing page 1 
Processing page 64 
Processing page 127 
Processing page 190 
Processing page 65 
Processing page 2 
Processing page 128 
Processing page 191 

而是,我想先處理頁面1,2,3,4,然後繼續按照列表中的順序。有沒有這樣做的選擇?

+0

你是說你想將任務分解到多個內核,但仍然按順序運行嗎?或者,您想要按正確順序處理已處理的網址的輸出列表。你的問題建議第一個。 –

+0

第一個。就像你會在下載管理器中設置「最大並行下載」一樣,但它們仍然按順序運行。我想要處理4個URL,例如:從1,2,3,4開始。如果3完成並且1,2,4仍在運行,請啓動第5個(http://example.com/page=5) – Hyperion

+0

但是,如果您的輔助函數具有返回值,則返回值的結果列表的順序對應於輸入參數列表的順序。即使工作人員的功能是無序處理的。 – elcombato

回答

1

如果不通過參數CHUNKSIZE地圖將計算使用該算法塊:

chunksize, extra = divmod(len(iterable), len(self._pool) * 4) 
if extra: 
    chunksize += 1 

它cuting您可迭代到task_batches和sperate進程中運行它。這就是爲什麼它不合適。解決方法是將塊設爲1.

import multiprocessing 
import time 

list_test = range(10) 

def proces(task): 
    print "task:", task 
    time.sleep(1) 

pool = multiprocessing.Pool(processes=3) 
pool.map(proces, list_test, chunksize=1) 

task: 0 
task: 1 
task: 2 
task: 3 
task: 4 
task: 5 
task: 6 
task: 7 
task: 8 
task: 9 
+2

請注意,在大多數情況下,'chunksize = 1'會嚴重影響性能。 – BallpointBen

0

多處理是一個異步操作,意思是它是按照定義非順序的。線程(或python的case進程)從你的列表中拉出url,並且不保證哪個進程會先完成。因此url 1可能會在url 64之前開始處理,但由於網絡I/O中的隨機性,例如url 64可能會先完成。

問問自己是否真的需要首先執行這些操作。如果答案是肯定的,那麼最好的辦法就是執行一個阻止步驟 - 先強制所有並行計算完成,然後對完成的結果進行排序。因此,如果您的URL列表非常大,並且您希望某些順序元素仍然可以利用並行化,則可以將您的列表分塊,然後通過上面的並行邏輯按順序運行每個塊。

相關問題