Dans l'exemple de code ci-dessous, j'aimerais récupérer la valeur de retour de la fonction worker
. Comment puis-je faire cela? Où cette valeur est-elle stockée?
Exemple de code:
import multiprocessing
def worker(procnum):
'''worker function'''
print str(procnum) + ' represent!'
return procnum
if __name__ == '__main__':
jobs = []
for i in range(5):
p = multiprocessing.Process(target=worker, args=(i,))
jobs.append(p)
p.start()
for proc in jobs:
proc.join()
print jobs
Production:
0 represent!
1 represent!
2 represent!
3 represent!
4 represent!
[<Process(Process-1, stopped)>, <Process(Process-2, stopped)>, <Process(Process-3, stopped)>, <Process(Process-4, stopped)>, <Process(Process-5, stopped)>]
Je n'arrive pas à trouver l'attribut pertinent dans les objets stockés dans jobs
.
multiprocessing.Queue
, plutôt qu'unManager
ici. L'utilisation de aManager
nécessite de créer un processus entièrement nouveau, ce qui est excessif quand unQueue
ferait l'affaire.multiprocessing.Pool.map
pour traiter votre liste d'éléments de travail.args=(my_function_argument, )
. Notez la,
virgule ici! Ou bien Python se plaindra "d'arguments positionnels manquants". Il m'a fallu 10 minutes pour comprendre. Vérifiez également l' utilisation manuelle (dans la section "classe de processus").Je pense que l'approche suggérée par @sega_sai est la meilleure. Mais il a vraiment besoin d'un exemple de code, alors voici:
Ce qui imprimera les valeurs de retour:
Si vous connaissez
map
(le Python 2 intégré), cela ne devrait pas être trop difficile. Sinon, jetez un œil au lien de sega_Sai .Notez combien peu de code est nécessaire. (Notez également comment les processus sont réutilisés).
la source
getpid()
retour a-t-il la même valeur? J'utilise Python3pool.map
une gamme de 1 000 000 en utilisant plus de 10 processus, je vois au plus deux pids différents.pool.apply_async
: docs.python.org/3/libraryCet exemple montre comment utiliser une liste d' instances multiprocessing.Pipe pour renvoyer des chaînes à partir d'un nombre arbitraire de processus:
Production:
Cette solution utilise moins de ressources qu'une multiprocessing.Queue qui utilisations
ou un multiprocessing.SimpleQueue qui utilise
Il est très instructif d'examiner la source de chacun de ces types.
la source
Pipe
par processus contre uneQueue
pour tous les processus. Je ne sais pas si cela finit par être plus efficace dans tous les cas.Pour une raison quelconque, je n'ai pas trouvé d'exemple général sur la façon de faire cela
Queue
n'importe où (même les exemples de doc de Python ne génèrent pas plusieurs processus), alors voici ce que j'ai travaillé après 10 essais:Queue
est une file d'attente bloquante et sécurisée pour les threads que vous pouvez utiliser pour stocker les valeurs de retour des processus enfants. Vous devez donc transmettre la file d'attente à chaque processus. Quelque chose de moins évident ici est que vous devez sortirget()
de la file d'attente avant dejoin
l'Process
es ou bien la file d'attente se remplit et bloque tout.Mise à jour pour ceux qui sont orientés objet (testé en Python 3.4):
la source
Pour toute autre personne qui cherche comment obtenir une valeur d'une
Process
utilisationQueue
:la source
Queue
de ma fonction, il me laisse passer lejoin()
queue.put(ret)
avant d'appelerp.start()
? Dans ce cas, le thread de travail sera suspendu pourqueue.get()
toujours. Vous pouvez reproduire cela en copiant mon extrait ci-dessus tout en commentantqueue.put(ret)
.queue.get()
doit arriver avant lep.join()
. Cela fonctionne maintenant pour moi.Il semble que vous devriez utiliser le multitraitement. classe la place et utiliser les méthodes .apply () .apply_async (), map ()
http://docs.python.org/library/multiprocessing.html?highlight=pool#multiprocessing.pool.AsyncResult
la source
Vous pouvez utiliser la fonction
exit
intégrée pour définir le code de sortie d'un processus. Il peut être obtenu à partir de l'exitcode
attribut du processus:Production:
la source
Le paquet Pebble a une belle exploitation d'abstraction
multiprocessing.Pipe
qui rend cela assez simple:Exemple tiré de: https://pythonhosted.org/Pebble/#concurrent-decorators
la source
Je pensais que je simplifierais les exemples les plus simples copiés ci-dessus, en travaillant pour moi sur Py3.6. Le plus simple est
multiprocessing.Pool
:Vous pouvez définir le nombre de processus dans la piscine avec, par exemple,
Pool(processes=5)
. Cependant, la valeur par défaut est le nombre de processeurs, alors laissez ce champ vide pour les tâches liées au processeur. (Les tâches liées aux E / S conviennent souvent aux threads de toute façon, car les threads attendent la plupart du temps et peuvent partager un cœur de processeur.) AppliquePool
également l' optimisation de la segmentation .(Notez que la méthode de travail ne peut pas être imbriquée dans une méthode. J'ai initialement défini ma méthode de travail à l'intérieur de la méthode qui fait l'appel
pool.map
, pour qu'elle reste entièrement autonome, mais les processus n'ont pas pu l'importer et j'ai jeté "AttributeError : Impossible de sélectionner l'objet local external_method..inner_method ". Plus d'informations ici . Cela peut être à l'intérieur d'une classe.)(J'apprécie l'impression de la question d'origine
'represent!'
plutôt quetime.sleep()
, mais sans elle, je pensais que du code s'exécutait simultanément alors qu'il ne l'était pas.)Py3
ProcessPoolExecutor
est également composé de deux lignes (.map
renvoie un générateur donc vous avez besoin dulist()
):Avec plaine
Process
:À utiliser
SimpleQueue
si tout ce dont vous avez besoin estput
etget
. La première boucle démarre tous les processus, avant que la seconde effectue lesqueue.get
appels de blocage . Je ne pense pas qu'il y ait de raison d'appelerp.join()
aussi.la source
Une solution simple:
Production:
la source
Si vous utilisez Python 3, vous pouvez utiliser
concurrent.futures.ProcessPoolExecutor
comme abstraction pratique:Production:
la source
J'ai modifié un peu la réponse de vartec car j'avais besoin d'obtenir les codes d'erreur de la fonction. (Merci vertec !!! c'est un truc génial)
Cela peut également être fait avec un
manager.list
mais je pense qu'il est préférable de l'avoir dans un dict et d'y stocker une liste. De cette façon, nous conservons la fonction et les résultats car nous ne pouvons pas être sûrs de l'ordre dans lequel la liste sera remplie.la source