2010-07-09 6 views
36

Quiero un proceso de larga duración para devolver su progreso a través de una cola (o algo similar) que alimentaré a un cuadro de diálogo de barra de progreso. También necesito el resultado cuando el proceso se completa. Aquí falla un ejemplo de prueba con RuntimeError: Queue objects should only be shared between processes through inheritance.¿Cómo se pasa una referencia de cola a una función administrada por pool.map_async()?

import multiprocessing, time 

def task(args): 
    count = args[0] 
    queue = args[1] 
    for i in xrange(count): 
     queue.put("%d mississippi" % i) 
    return "Done" 

def main(): 
    q = multiprocessing.Queue() 
    pool = multiprocessing.Pool() 
    result = pool.map_async(task, [(x, q) for x in range(10)]) 
    time.sleep(1) 
    while not q.empty(): 
     print q.get() 
    print result.get() 

if __name__ == "__main__": 
    main() 

he sido capaz de conseguir que esto funcione utilizando objetos individuales del proceso (en el que estoy alowed a pasar una referencia de cola), pero entonces no tener una piscina para manejar los muchos procesos que quiero almorzar. ¿Algún consejo sobre un mejor patrón para esto?

+0

No es una respuesta a su pregunta, pero intente con la biblioteca 'execnet' para asignaciones multiproceso. El 'multiprocesamiento' integrado aún tiene algunos problemas por resolver (ver el rastreador de Python). Además de que su código fuente es bastante grande y complicado. La biblioteca 'execnet' se ve mucho mejor para mí que' multiprocesamiento'. –

Respuesta

43

El siguiente código parece funcionar:

import multiprocessing, time 

def task(args): 
    count = args[0] 
    queue = args[1] 
    for i in xrange(count): 
     queue.put("%d mississippi" % i) 
    return "Done" 


def main(): 
    manager = multiprocessing.Manager() 
    q = manager.Queue() 
    pool = multiprocessing.Pool() 
    result = pool.map_async(task, [(x, q) for x in range(10)]) 
    time.sleep(1) 
    while not q.empty(): 
     print q.get() 
    print result.get() 

if __name__ == "__main__": 
    main() 

Tenga en cuenta que la cola se obtuvo a partir de un manager.Queue() en lugar de multiprocessing.Queue(). Gracias Alex por señalarme en esta dirección.

+0

+1 y solo una nota rápida de que su pregunta me ayudó en un problema que tuve hoy. Encontré la versión Manager de la cola, pero mi código no funcionaba porque confiaba en un global. Debe pasarse como un parámetro, como lo está haciendo. – winwaed

+0

También +1 para 'manager.Queue' - muy útil. – fantabolous

8

Haciendo q trabajos globales ...:

import multiprocessing, time 

q = multiprocessing.Queue() 

def task(count): 
    for i in xrange(count): 
     q.put("%d mississippi" % i) 
    return "Done" 

def main(): 
    pool = multiprocessing.Pool() 
    result = pool.map_async(task, range(10)) 
    time.sleep(1) 
    while not q.empty(): 
     print q.get() 
    print result.get() 

if __name__ == "__main__": 
    main() 

Si necesita varias colas, por ejemplo para evitar mezclar el progreso de los diversos procesos del grupo, debería funcionar una lista global de colas (por supuesto, cada proceso necesitará saber qué índice en la lista a usar, pero está bien pasarlo como argumento;)

+0

¿Funcionará esto si la "tarea" está definida en un módulo o paquete diferente? El código de ejemplo es muy simplificado. El programa real tiene una arquitectura MVC en la que una canalización productor-consumidor está configurada en varios núcleos (el modelo) y necesita enviar actualizaciones de progreso a la GUI de wxPython (la Vista). – David

+2

@David, puedes intentarlo; si su código real no funciona de esta manera simple, tendrá que subir de nivel en complejidad e ir por un administrador (que puede darle proxies para colas, etc.). –

+0

Esto no parece funcionar en absoluto. q nunca devuelve nada q. vacío() siempre es verdadero en mi máquina. Incluso si aumente la llamada de espera a 10 segundos, lo que debería ser un tiempo excesivo para que la tarea ponga algunos mensajes en la cola, q.empty siempre devuelve True. – David

Cuestiones relacionadas