2012-03-24 190 views
5

我有一個可以並行下載多個文件的下載器函數。 我使用multiprocessing.Pool.map_async爲了下載同一文件的不同塊。 我想顯示下載的狀態欄。爲此,我需要知道已經下載的總字節數(total_bytes_dl)。在進程之間共享變量

pool = multiprocessing.Pool(processes) 
    mapObj = pool.map_async(f, args) 

    while not mapObj.ready(): 
     status = r"%.2f MB/%.2f MB" % (total_bytes_dl/1024.0/1024.0, filesize/1024.0/1024.0,) 
     status = status + chr(8)*(len(status)+1) 
     print status, 
     time.sleep(0.5) 

有沒有一種方法來設置,將所有這些過程和主要過程之間共享的變量,所以每一個過程可以追加剛剛下載的字節的數量?

回答

3

的解決方案是intilize新的過程,並通過所述共享ctypes的值:

from ctypes import c_int 
import dummy 

shared_bytes_var = multiprocessing.Value(c_int) 

def Func(...): 
    .... 
    pool = multiprocessing.Pool(initializer=_initProcess,initargs=(shared_bytes_var,)) 
    .... 

def _initProcess(x): 
    dummy.shared_bytes_var = x 
1

當然,你可以在共​​享內存中使用共享的​​值,如果你只是想下載它應該做的字節。傳遞每個工作人員的相關價值,並且調用過程將有權訪問它。

看到: http://docs.python.org/library/multiprocessing.html#shared-ctypes-objects

+2

你不能映射ctypes共享對象:'RuntimeError:同步對象只能通過繼承在進程間共享' – iTayb 2012-03-24 23:41:24

0

你可以使用多進程隊列對象,工人可以用它來發送的狀態數據。您的主進程必須從隊列中讀取狀態條目並相應地更新狀態。

1

使用分配這樣的隊列對象:

que = multiprocessing.Manager().Queue() 

這個變量傳遞給工人,並且它們可以使用que.put(bytes)至 定期報告他們自上次報告以來已經下載了多少。您 然後就檢查隊列的大小和拉在任何收到的報告:

downloaded = 0 
while not mapObj.ready(): 
    for _ in range(q.qsize()): 
     downloaded += q.get() 
    print downloaded, r"bytes downloaded\r", 
    time.sleep(0.5) 

注:雖然模塊還提供了一種方法multiprocessing.Queue(),它不完全等同於multiprocessing.Manager().Queue()。見this question,和答案。