Erfahren Sie mehr über Python Multiprocessing (aus einem PMOTW-Artikel ) und würden Sie gerne klarstellen, was genau die join()
Methode tut.
In einem alten Tutorial aus dem Jahr 2008 heißt es, dass ohne den p.join()
Aufruf im folgenden Code "der untergeordnete Prozess im Leerlauf bleibt und nicht beendet wird und zu einem Zombie wird, den Sie manuell töten müssen".
from multiprocessing import Process
def say_hello(name='world'):
print "Hello, %s" % name
p = Process(target=say_hello)
p.start()
p.join()
Ich habe einen Ausdruck von PID
sowie einen time.sleep
zu testenden hinzugefügt und soweit ich das beurteilen kann, endet der Prozess von selbst:
from multiprocessing import Process
import sys
import time
def say_hello(name='world'):
print "Hello, %s" % name
print 'Starting:', p.name, p.pid
sys.stdout.flush()
print 'Exiting :', p.name, p.pid
sys.stdout.flush()
time.sleep(20)
p = Process(target=say_hello)
p.start()
# no p.join()
innerhalb von 20 Sekunden:
936 ttys000 0:00.05 /Library/Frameworks/Python.framework/Versions/2.7/Reso
938 ttys000 0:00.00 /Library/Frameworks/Python.framework/Versions/2.7/Reso
947 ttys001 0:00.13 -bash
nach 20 Sekunden:
947 ttys001 0:00.13 -bash
Das Verhalten ist dasselbe, p.join()
wenn am Ende der Datei wieder hinzugefügt wird. Das Python-Modul der Woche bietet eine gut lesbare Erklärung des Moduls . "Um zu warten, bis ein Prozess seine Arbeit abgeschlossen und beendet hat, verwenden Sie die join () -Methode.", Aber es scheint, dass zumindest OS X dies trotzdem getan hat.
Ich wundere mich auch über den Namen der Methode. .join()
Verkettet die Methode hier etwas? Verkettet es einen Prozess mit seinem Ende? Oder teilt es nur einen Namen mit Pythons nativer .join()
Methode?
quelle
CPU, Memory resources
vom übergeordneten Prozess getrenntjoin
und nach Abschluss des untergeordneten Prozesses wieder zurückgesetzt?Antworten:
Das
join()
Verfahren, wenn verwendet mitthreading
odermultiprocessing
wird nicht im Zusammenhang mitstr.join()
- es ist nicht wirklich etwas verketten zusammen. Es bedeutet vielmehr nur "Warten Sie, bis dieser [Thread / Prozess] abgeschlossen ist". Der Namejoin
wird verwendet, da diemultiprocessing
API desthreading
Moduls der API desthreading
Moduls ähneln soll und das Moduljoin
für seinThread
Objekt verwendet. Die Verwendung des Begriffsjoin
"Warten auf den Abschluss eines Threads" ist in vielen Programmiersprachen üblich, daher hat Python ihn auch übernommen.Der Grund für die Verzögerung von 20 Sekunden mit und ohne Aufruf von
join()
ist, dass der Hauptprozess standardmäßigjoin()
alle laufendenmultiprocessing.Process
Instanzen aufruft, wenn er zum Beenden bereit ist . Dies ist in denmultiprocessing
Dokumenten nicht so klar angegeben, wie es sein sollte, wird jedoch im Abschnitt Programmierrichtlinien erwähnt :Sie können dieses Verhalten überschreiben, indem Sie vor dem Starten des Prozesses das
daemon
Flag aufProcess
to setzenTrue
:Wenn Sie dies tun, wird der untergeordnete Prozess beendet, sobald der Hauptprozess abgeschlossen ist :
quelle
p.daemon=True
diente, "einen Hintergrundprozess zu starten, der ausgeführt wird, ohne das Beenden des Hauptprogramms zu blockieren". Aber wenn "Der Dämonprozess wird automatisch beendet, bevor das Hauptprogramm beendet wird", was genau wird er verwendet?daemonic
untergeordneten Prozesses nicht sehr sicher ist, da der Prozess beendet wird, ohne dass offene Ressourcen bereinigt werden müssen. (Forts.)multiprocessing
API so konzipiert ist, dass sie diethreading
API so genau wie möglich nachahmt . Dämonischethreading.Thread
Objekte werden beendet, sobald der Haupt-Thread beendet wird, sodass sich dämonischemultiprocesing.Process
Objekte genauso verhalten.Ohne das
join()
kann der Hauptprozess abgeschlossen werden, bevor der untergeordnete Prozess dies tut. Ich bin mir nicht sicher, unter welchen Umständen das zu Zombieismus führt.Der Hauptzweck von
join()
besteht darin, sicherzustellen, dass ein untergeordneter Prozess abgeschlossen ist, bevor der Hauptprozess etwas ausführt, das von der Arbeit des untergeordneten Prozesses abhängt.Die Etymologie von
join()
ist, dass es das Gegenteil von istfork
, was der übliche Begriff in Betriebssystemen der Unix-Familie zum Erstellen untergeordneter Prozesse ist. Ein einzelner Prozess "teilt" sich in mehrere und "verbindet" sich dann wieder zu einem.quelle
join()
weiljoin()
damit gewartet wird, bis einthreading.Thread
Objekt abgeschlossen ist, und diemultiprocessing
API soll diethreading
API so weit wie möglich nachahmen .join()
in dem Fall benötigt, in dem der Hauptthread die Ergebnisse der Arbeit der Unter-Threads benötigt. Wenn Sie beispielsweise etwas rendern und jedem der vier Unterprozesse 1/4 des endgültigen Bilds zuweisen und das gesamte Bild anzeigen möchten, wenn es fertig ist.Ich werde nicht im Detail erklären, was
join
tut, aber hier ist die Etymologie und die Intuition dahinter, die Ihnen helfen sollen, sich leichter an ihre Bedeutung zu erinnern.Die Idee ist, dass die Ausführung in mehrere Prozesse " zerfällt ", von denen einer der Master, die restlichen Arbeiter (oder "Slaves") ist. Wenn die Arbeiter fertig sind, "treten" sie dem Master bei, damit die serielle Ausführung fortgesetzt werden kann.
Die
join
Methode bewirkt, dass der Master-Prozess darauf wartet, dass ein Mitarbeiter ihm beitritt. Die Methode könnte besser als "Warten" bezeichnet worden sein, da dies das tatsächliche Verhalten ist, das sie im Master verursacht (und so wird sie in POSIX genannt, obwohl POSIX-Threads sie auch "Join" nennen). Das Verbinden erfolgt nur, wenn die Threads ordnungsgemäß zusammenarbeiten. Dies ist nicht etwas, was der Master tut .Die Namen "Fork" und "Join" werden seit 1963 in der Mehrfachverarbeitung mit dieser Bedeutung verwendet .
quelle
join
seiner Verwendung in Bezug auf die Verkettung vorausgegangen sein, im Gegensatz zur Umkehrung.join()
wird verwendet, um auf das Beenden der Worker-Prozesse zu warten. Man muss anrufenclose()
oderterminate()
vor der Verwendungjoin()
.Wie bei @Russell erwähnt , ist Join wie das Gegenteil von Fork (das Subprozesse von Spawns erzeugt).
Damit Join beitreten kann, müssen Sie ausführen, um zu
close()
verhindern, dass weitere Aufgaben an den Pool gesendet werden, und um zu beenden, sobald alle Aufgaben abgeschlossen sind. Alternativ wird das Ausführenterminate()
einfach beendet, indem alle Arbeitsprozesse sofort gestoppt werden."the child process will sit idle and not terminate, becoming a zombie you must manually kill"
Dies ist möglich, wenn der Hauptprozess (übergeordneter Prozess) beendet wird, der untergeordnete Prozess jedoch noch ausgeführt wird und nach Abschluss kein übergeordneter Prozess mehr vorhanden ist, auf den der Beendigungsstatus zurückgesetzt werden kann.quelle
Der
join()
Aufruf stellt sicher, dass nachfolgende Zeilen Ihres Codes nicht aufgerufen werden, bevor alle Mehrfachverarbeitungsprozesse abgeschlossen sind.Ohne das
join()
wird der folgende Code beispielsweiserestart_program()
noch vor Abschluss der Prozesse aufgerufen. Dies ähnelt asynchron und ist nicht das, was wir wollen (Sie können es versuchen):quelle
Verwenden Sie die Methode join (), um zu warten, bis ein Prozess seine Arbeit abgeschlossen und beendet hat.
und
Hinweis Es ist wichtig, dem Prozess nach dem Beenden beizutreten (), damit die Hintergrundmaschine Zeit hat, den Status des Objekts zu aktualisieren, um die Beendigung widerzuspiegeln.
Dies ist ein gutes Beispiel, das mir geholfen hat, es zu verstehen: hier
Eine Sache, die mir persönlich aufgefallen ist, war, dass mein Hauptprozess angehalten wurde, bis das Kind seinen Prozess mit der join () -Methode beendet hatte, die den Punkt, den ich überhaupt benutzte, besiegte
multiprocessing.Process()
.quelle