2012-03-24 24 views
5

Tengo una función de descarga que descarga múltiples archivos de forma paralela. Uso multiprocessing.Pool.map_async para descargar diferentes fragmentos del mismo archivo. Me gustaría mostrar una barra de estado de la descarga. Para esto, necesito saber el total de bytes que ya ha sido descargado (total_bytes_dl).Compartiendo una variable entre procesos

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) 

¿Hay una manera de establecer una variable que será compartido entre todos estos procesos y el proceso principal, por lo que cada proceso puede añadir la cantidad de bytes que acaba de descargar?

Respuesta

3

La solución fue intilize el nuevo proceso y pasar el valor ctypes compartida:

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

Claro, puede utilizar los valores ctypes compartidos en la memoria compartida, si solo quiere que se descarguen los bytes, debería hacerlo. pase el valor relevante para cada trabajador, y el proceso de llamada tendrá acceso a él.

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

+2

no se puede asignar el objeto compartido ctypes: 'RuntimeError: los objetos sincronizados solo se deben compartir entre procesos a través de la herencia' – iTayb

0

Se puede usar un objeto Queue multiproceso que los trabajadores podrían utilizar para enviar datos de estado en. Su proceso principal tendrá que leer las entradas de estado de la cola y actualizar el estado en consecuencia.

1

con un objeto de cola asignado como esto:

que = multiprocessing.Manager().Queue() 

pasar esta variable a los trabajadores, y puede usar que.put(bytes) a informar periódicamente cuánto han descargado desde su último informe. Usted a continuación, sólo comprueba el tamaño de cola y tire de éste en ningún informe entrantes:

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

Nota: Aunque el módulo también proporciona un método multiprocessing.Queue(), no es totalmente equivalente a multiprocessing.Manager().Queue(). Ver this question, y la respuesta.

Cuestiones relacionadas