web-dev-qa-db-fra.com

Comment transmettez-vous une référence de file d'attente à une fonction gérée par piscine.map_async ()?

Je veux un processus de longue date de retourner sa progression sur une file d'attente (ou quelque chose de similaire) que je vais alimenter dans une boîte de dialogue Barre de progression. J'ai également besoin du résultat lorsque le processus est terminé. Un exemple de test ici échoue avec un RuntimeError: Queue objects should only be shared between processes through inheritance.

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()

J'ai été capable de faire fonctionner cela à l'aide d'objets de processus individuels (où i AM est affilé pour passer une référence de la file d'attente) mais je n'ai pas de piscine pour gérer les nombreux processus que je veux lancer . Des conseils sur un meilleur modèle pour cela?

39
David

Le code suivant semble fonctionner:

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()

Notez que la file d'attente est issue d'un gestionnaire.Queue () plutôt que multiprocessing.Queue (). Merci Alex pour me faire remarquer dans cette direction.

50
David

Fabriquer qglobal fonctionne ...:

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 vous avez besoin de plusieurs files d'attente, par exemple. Pour éviter de mélanger les progrès des divers processus de piscine, une liste mondiale de files d'attente devrait fonctionner (bien sûr, chaque processus devra alors savoir quoi index dans la liste à utiliser, mais c'est correct pour passer comme un argument ;-).

7
Alex Martelli