2012-03-24 140 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,和答案。