Im folgenden Beispielcode möchte ich den Rückgabewert der Funktion wiederherstellen worker
. Wie kann ich das machen? Wo ist dieser Wert gespeichert?
Beispielcode:
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
Ausgabe:
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)>]
Ich kann das relevante Attribut in den darin gespeicherten Objekten nicht finden jobs
.
multiprocessing.Queue
eher die Verwendung von a als vonManager
hier empfehlen . Die Verwendung vonManager
erfordert das Laichen eines völlig neuen Prozesses, der übertrieben ist, wenn aQueue
dies tun würde.multiprocessing.Pool.map
, Ihre Liste der Arbeitselemente zu verarbeiten.args=(my_function_argument, )
. Beachten Sie das,
Komma hier! Andernfalls beschwert sich Python über "fehlende Positionsargumente". Ich habe 10 Minuten gebraucht, um das herauszufinden. Überprüfen Sie auch die manuelle Verwendung (im Abschnitt "Prozessklasse").Ich denke, der von @sega_sai vorgeschlagene Ansatz ist der bessere. Aber es braucht wirklich ein Codebeispiel, also geht es weiter:
Welches gibt die Rückgabewerte aus:
Wenn Sie mit
map
(dem integrierten Python 2) vertraut sind, sollte dies nicht zu schwierig sein. Ansonsten schau dir den Link von sega_Sai an .Beachten Sie, wie wenig Code benötigt wird. (Beachten Sie auch, wie Prozesse wiederverwendet werden).
quelle
getpid()
Rückgabe alle den gleichen Wert hat? Ich verwende Python3pool.map
einen Bereich von 1.000.000 mit mehr als 10 Prozessen füttere, sehe ich höchstens zwei verschiedene Pids.pool.apply_async
: docs.python.org/3/library/…Dieses Beispiel zeigt, wie eine Liste von Multiprocessing.Pipe- Instanzen verwendet wird, um Zeichenfolgen aus einer beliebigen Anzahl von Prozessen zurückzugeben:
Ausgabe:
Diese Lösung verbraucht weniger Ressourcen als eine Multiprocessing.Queue, die verwendet wird
oder eine Multiprocessing.SimpleQueue, die verwendet
Es ist sehr lehrreich, die Quelle für jeden dieser Typen zu betrachten.
quelle
Pipe
pro Prozess gegenüber einerQueue
für alle Prozesse erstellen. Ich weiß nicht, ob das in allen Fällen effizienter ist.Aus irgendeinem Grund konnte ich
Queue
nirgendwo ein allgemeines Beispiel dafür finden (selbst Pythons Dokumentbeispiele erzeugen nicht mehrere Prozesse). Nach 10 Versuchen habe ich Folgendes getan:Queue
ist eine blockierende, threadsichere Warteschlange, in der Sie die Rückgabewerte der untergeordneten Prozesse speichern können. Sie müssen also die Warteschlange an jeden Prozess übergeben. Etwas weniger offensichtliches ist hier, dass Sieget()
aus der Warteschlange müssen, bevor Siejoin
dieProcess
es oder die Warteschlange füllt und blockiert alles.Update für objektorientierte Benutzer (getestet in Python 3.4):
quelle
Für alle anderen, die suchen, wie sie einen Wert aus einer
Process
Verwendung ziehen könnenQueue
:quelle
Queue
aus meiner Funktion entferne , kann ich dasjoin()
queue.put(ret)
vor dem Anruf anp.start()
? In diesem Fall bleibt der Worker-Thread für immer hängenqueue.get()
. Sie können dies replizieren, indem Sie meinen obigen Ausschnitt kopieren, während Sie ihn auskommentierenqueue.put(ret)
.queue.get()
muss vor dem passierenp.join()
. Es funktioniert jetzt für mich.Es scheint, dass Sie stattdessen die Klasse multiprocessing.Pool verwenden und die Methoden .apply () .apply_async (), map () verwenden sollten.
http://docs.python.org/library/multiprocessing.html?highlight=pool#multiprocessing.pool.AsyncResult
quelle
Mit der integrierten Funktion können Sie
exit
den Exit-Code eines Prozesses festlegen. Es kann aus demexitcode
Attribut des Prozesses erhalten werden:Ausgabe:
quelle
Das Kieselpaket hat eine nette Abstraktion,
multiprocessing.Pipe
die dies recht einfach macht:Beispiel von: https://pythonhosted.org/Pebble/#concurrent-decorators
quelle
Ich dachte, ich würde die einfachsten Beispiele, die von oben kopiert wurden, vereinfachen und für mich an Py3.6 arbeiten. Am einfachsten ist
multiprocessing.Pool
:Sie können die Anzahl der Prozesse im Pool festlegen, z
Pool(processes=5)
. Standardmäßig wird jedoch die CPU-Anzahl verwendet. Lassen Sie diese Option daher für CPU-gebundene Aufgaben leer. (E / A-gebundene Aufgaben passen ohnehin oft zu Threads, da die Threads meistens warten und einen CPU-Kern gemeinsam nutzen können.) WendetPool
auch die Chunking-Optimierung an .(Beachten Sie, dass die Worker-Methode nicht in einer Methode verschachtelt werden kann. Ich habe meine Worker-Methode zunächst in der Methode definiert, die aufgerufen
pool.map
wird, um alles in sich geschlossen zu halten, aber dann konnten die Prozesse sie nicht importieren und haben "AttributeError" ausgelöst : Lokales Objekt Outer_Method..inner_method kann nicht ausgewählt werden. Mehr hier . Es kann sich innerhalb einer Klasse befinden.)(Schätzen Sie den Druck der ursprünglichen Frage
'represent!'
und nichttime.sleep()
, aber ohne sie dachte ich, dass ein Code gleichzeitig ausgeführt wird, wenn dies nicht der Fall ist.)Py3
ProcessPoolExecutor
ist auch zwei Zeilen (.map
gibt einen Generator zurück, so dass Sie die benötigenlist()
):Mit schlicht
Process
es:Verwenden Sie,
SimpleQueue
wenn Sie nurput
und benötigenget
. Die erste Schleife startet alle Prozesse, bevor die zweite die blockierendenqueue.get
Aufrufe ausführt . Ich glaube nicht, dass es einen Grund gibt, auch anzurufenp.join()
.quelle
Eine einfache Lösung:
Ausgabe:
quelle
Wenn Sie Python 3 verwenden, können Sie Folgendes verwenden
concurrent.futures.ProcessPoolExecutor
:Ausgabe:
quelle
Ich habe die Antwort von vartec ein wenig geändert, da ich die Fehlercodes von der Funktion erhalten musste. (Danke vertec !!! es ist ein toller Trick)
Dies kann auch mit einem gemacht werden,
manager.list
aber ich denke, es ist besser, es in einem Diktat zu haben und eine Liste darin zu speichern. Auf diese Weise behalten wir die Funktion und die Ergebnisse bei, da wir nicht sicher sind, in welcher Reihenfolge die Liste gefüllt wird.quelle