Wer führt die callback-bei Verwendung apply_async Methode einer multiprocessing-pool?
Ich versuche zu verstehen, ein wenig von dem, was passiert hinter den kulissen bei der Verwendung der apply_sync Methode einer multiprocessing-pool.
Wer führt die callback-Methode? Es ist der wichtigste Prozess, genannt apply_async?
Sagen wir mal ich schicke eine ganze Reihe von apply_async Befehle mit callbacks und dann weiter mit meinem Programm. Mein Programm ist immer noch, Dinge zu tun, wenn die apply_async ist von Anfang bis Ende. Wie funktioniert die callback laufen zu bekommen mein "main-Prozess", während sich der Haupt-Prozess ist noch immer damit beschäftigt, das Skript?
Hier ist ein Beispiel.
import multiprocessing
import time
def callback(x):
print '{} running callback with arg {}'.format(multiprocessing.current_process().name, x)
def func(x):
print '{} running func with arg {}'.format(multiprocessing.current_process().name, x)
return x
pool = multiprocessing.Pool()
args = range(20)
for a in args:
pool.apply_async(func, (a,), callback=callback)
print '{} going to sleep for a minute'.format(multiprocessing.current_process().name)
t0 = time.time()
while time.time() - t0 < 60:
pass
print 'Finished with the script'
Die Ausgabe ist so etwas wie
PoolWorker-1 läuft func arg-0
PoolWorker-2 mit func arg-1
PoolWorker-3 ausgeführt func arg-2
MainProcess dem schlafen gehen für eine minute <-- main-Prozess beschäftigt ist
PoolWorker-4 mit func arg-3
PoolWorker-1 läuft func arg-4
PoolWorker-2 mit func arg-5
PoolWorker-3 ausgeführt func arg-6
PoolWorker-4 mit func arg-7
MainProcess ausführen von callback-arg-0 <-- main-Prozess ausgeführt wird, der Rückruf, während es immer noch in der while-Schleife!!
MainProcess ausführen von callback mit arg-1
MainProcess ausführen von callback-arg-2
MainProcess ausführen von callback-arg-3
MainProcess ausführen von callback-arg-4
PoolWorker-1 läuft func arg-8
...
Fertig mit Skript
Wie ist MainProcess ausführen der callback-während es in der Mitte der while-Schleife??
Gibt es da die Aussage über den Rückruf in der Dokumentation für multiprocessing.Pool, das scheint wie ein Tipp, aber ich verstehe es nicht.
apply_async(func[, args[, kwds[, callback]]])
Einer Variante der apply () - Methode liefert ein Ergebnis-Objekt.
Wenn callback angegeben ist, dann sollte es ein callable, das akzeptiert ein einzelnes argument. Wenn das Ergebnis wird bereit callback angewendet wird (es sei denn der Anruf fehlgeschlagen). Rückruf sollte sofort abgeschlossen werden, da sonst der thread behandelt die Ergebnisse werden blockiert.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Es ist in der Tat ein Hinweis in der Dokumentation:
Rückrufe behandelt werden die wichtigsten Verfahren, aber Sie laufen in einer eigenen thread. Beim erstellen einer
Pool
es tatsächlich schafft ein paarThread
Objekte intern:Den interessanten thread für uns ist
_result_handler
; wir kommen zu kurz, warum.Umschaltgetriebe für einen zweiten, wenn Sie Sie ausführen
apply_async
wird, wird einApplyResult
Objekt intern verwalten immer das Ergebnis vom Kind:Wie Sie sehen können, die
_set
Methode ist die eine, die endet eigentlich die Ausführung dercallback
übergeben, vorausgesetzt, die Aufgabe erfolgreich war. Beachten Sie auch, dass es fügt sich zu einem globalencache
dict am Ende__init__
.Nun, zurück zu den
_result_handler
thread-Objekt. Das Objekt ruft die_handle_results
Funktion, die wie folgt aussieht:Es ist eine Schleife, die zieht nur die Ergebnisse von Kindern aus der Warteschlange, findet den Eintrag in
cache
, und fordert_set
führt unser callback. Es ist in der Lage zu laufen, obwohl Sie in einer Schleife, weil es nicht läuft im Haupt-thread._result_handler
thread zieht eine abgeschlossene Aufgabe aus der Warteschlange, ruft_set
(läuft der callback), dann bewegt sich auf die nächste. Dies ist der Grund, warum die Dokumentation sagt, machen Sie sicher, dass der callback sofort abgeschlossen; die Ausführung der callback-Blöcke weitere Ergebnisse verarbeitet.