Je n'ai pas vu d'exemples clairs avec des cas d'utilisation pour Pool.apply , Pool.apply_async et Pool.map . J'utilise principalement Pool.map
; Quels sont les avantages des autres?
À l'époque ancienne de Python, pour appeler une fonction avec des arguments arbitraires, vous utiliseriez apply
:
apply(f,args,kwargs)
apply
existe toujours dans Python2.7 mais pas dans Python3 et n'est généralement plus utilisé. Aujourd'hui,
f(*args,**kwargs)
est préféré. Les modules multiprocessing.Pool
essaient de fournir une interface similaire.
Pool.apply
ressemble à Python apply
, sauf que l'appel de fonction est exécuté dans un processus séparé. Pool.apply
bloque jusqu'à ce que la fonction soit terminée.
Pool.apply_async
est également similaire à apply
de Python, à l'exception que l'appel retourne immédiatement au lieu d'attendre le résultat. Un objet AsyncResult
est renvoyé. Vous appelez sa méthode get()
pour récupérer le résultat de l'appel de fonction. La méthode get()
est bloquée jusqu'à ce que la fonction soit terminée. Ainsi, pool.apply(func, args, kwargs)
est équivalent à pool.apply_async(func, args, kwargs).get()
.
Contrairement à Pool.apply
, la méthode Pool.apply_async
dispose également d'un rappel qui, s'il est fourni, est appelé à la fin de la fonction. Ceci peut être utilisé au lieu d'appeler get()
.
Par exemple:
import multiprocessing as mp
import time
def foo_pool(x):
time.sleep(2)
return x*x
result_list = []
def log_result(result):
# This is called whenever foo_pool(i) returns a result.
# result_list is modified only by the main process, not the pool workers.
result_list.append(result)
def apply_async_with_callback():
pool = mp.Pool()
for i in range(10):
pool.apply_async(foo_pool, args = (i, ), callback = log_result)
pool.close()
pool.join()
print(result_list)
if __== '__main__':
apply_async_with_callback()
peut donner un résultat tel que
[1, 0, 4, 9, 25, 16, 49, 36, 81, 64]
Notez que, contrairement à pool.map
, l'ordre des résultats peut ne pas correspondre à l'ordre dans lequel les appels pool.apply_async
ont été effectués.
Donc, si vous avez besoin d'exécuter une fonction dans un processus séparé, mais que vous voulez que le processus actuel soit block jusqu'au retour de cette fonction, utilisez Pool.apply
. Comme Pool.apply
, Pool.map
bloque jusqu'au retour du résultat complet.
Si vous souhaitez que le pool de processus de travail effectue de nombreux appels de fonction de manière asynchrone, utilisez Pool.apply_async
. L'ordre ordre des résultats n'est pas garanti identique à l'ordre des appels à Pool.apply_async
.
Notez également que vous pouvez appeler plusieurs fonctions différentes avec Pool.apply_async
(tous les appels ne doivent pas nécessairement utiliser la même fonction).
En revanche, Pool.map
applique la même fonction à plusieurs arguments. Cependant, contrairement à Pool.apply_async
, les résultats sont renvoyés dans un ordre correspondant à l'ordre des arguments.
En ce qui concerne apply
vs map
:
pool.apply(f, args)
: f
n'est exécuté que par UN des ouvriers du pool. Ainsi, UN des processus du pool exécutera f(args)
.
pool.map(f, iterable)
: cette méthode divise l'itéré en plusieurs morceaux qu'elle soumet au pool de processus en tant que tâches distinctes. Vous profitez donc de tous les processus du pool.