2014-02-09 8 views
7

Aus dem Python-Terminal, ich einen Befehl wie den folgenden, führen Sie eine langlaufende Kind-Prozess zum Laichen:Python Multiprocessing und Unabhängigkeit von Kindern verarbeitet

from multiprocessing.process import Process 
Process(target=LONG_RUNNING_FUNCTION).start() 

Dieser Befehl gibt, und ich kann andere Dinge tun in Das Python-Terminal, aber alles, was vom Kind gedruckt wird, wird immer noch in meiner Python-Terminalsitzung gedruckt.

Wenn ich den Terminalausgang (entweder mit oder exit CTRL + D ), dem Kommando exit es hängt. Wenn ich CTRL + C während dieses Hangs trete, wird der untergeordnete Prozess beendet.

Wenn ich den Python-Terminal-Prozess manuell (über den Posix-Befehl kill) abbricht, ist der Kindprozess stattdessen verwaist und läuft weiter mit seiner vermutlich verworfenen Ausgabe.

Wenn ich diesen Code mit python -c laufen, wartet er auf das Kind zu beenden, und CTRL +C tötet Eltern und Kind.

Welche Konfigurationen von Python führen zum Abbruch von Kindern, wenn die Eltern beendet werden? Insbesondere, wenn ein Python-mod_wsgi-apache-Webserver untergeordnete Prozesse hervorbringt und dann neu gestartet wird, werden die Kinder getötet?

[Was ist der richtige Weg, um Kindprozesse, die aus dem Terminal hervorgehen, abzutrennen? Gibt es eine Möglichkeit eleganter als die folgenden: Deliberately make an orphan process in python]

Update: Python Subprozesse gelaicht mit multiprocessing.Process von einem Webserver unter Apache laufen ist nicht getötet, als Apache neu gestartet wird.

Antwort

12

Dies ist keine Frage, wie Sie python aufrufen; Es ist eine Funktion des Moduls multiprocessing. Wenn Sie dieses Modul importieren, wird dem übergeordneten Prozess ein Exit-Handler hinzugefügt, der die Objekte join() auf den Process-Objekten aller unter multiprocessing.Process erstellten untergeordneten Objekte aufruft, bevor das übergeordnete Element beendet werden kann. Wenn Sie auf diese Weise Child-Prozesse starten, gibt es keine Möglichkeit, ohne das Modulinnere zu hacken, um das Verhalten zu vermeiden, das Ihnen Probleme bereitet.

Wenn Sie einen Prozess starten möchten, der in der Lage ist, den Elternteil zu überleben, werden Sie wahrscheinlich besser mit subprocess.Popen bedient werden. Wenn das Kind auf diese Weise begonnen hat, werden die Eltern nicht versuchen, das Kind zu verbinden vor dem Beenden und stattdessen sofort verlassen, ein verwaistes Kind verlassen:

>>> from subprocess import Popen 
>>> Popen(["sleep", "100"]) 
<subprocess.Popen object at 0x10d3fedd0> 
>>> exit() 
alp:~ $ ps -opid,ppid,command | grep sleep | grep -v grep 
37979  1 sleep 100 

Gibt es einen bestimmten Grund, warum Sie verwenden multiprocessing statt subprocess ? Ersteres soll nicht dazu dienen, Kindprozesse zu erstellen, die das Elternteil überdauern sollen; Es dient dazu, untergeordnete Prozesse zu erstellen, die sinnvollerweise über CPUs hinweg parallelisiert werden können, um die Global Interpreter Lock zu umgehen. (Ich ignoriere die verteilten Fähigkeiten von multiprocessing für die Zwecke dieser Diskussion.) multiprocessing wird so normalerweise in jenen Fällen verwendet, in denen, wenn es kein GIL gäbe, Sie Threads verwenden würden. (Beachten Sie in diesem Zusammenhang, dass die API des Moduls multiprocessing dem Modell threading sehr ähnlich ist.)

Zu den spezifischen Fragen am Ende Ihrer Post: (1) Nichts über Python ist verantwortlich für das Töten von Kindern, wenn der Elternteil beendet wird. Ein Kind des Webservers wird nur getötet, wenn der Elternteil es vor dem Beenden tötet (oder wenn die gesamte Prozessgruppe getötet wird). (2) Die Methode, zu der Sie eine Verbindung herstellen, sieht so aus, als ob sie versucht, die Daemonisierung zu replizieren, ohne dabei die Standard-Idiome zu kennen. Es gibt eine Reihe von Paketen zum Erstellen von Daemon-Prozessen. Sie sollten stattdessen einen von ihnen verwenden.

+0

Subprozess ist mein Einstiegsmodul für das Dispatching von Systemaufrufen, aber die Verwendung von Subprozess zum Starten von Python-Hintergrundaufgaben erschien unangemessen. Hast du eine gute Python-Deamon-Bibliothek benutzt (zB Python-Deamon)? – Zags

+1

Die Unterscheidung zwischen Hintergrund und Vordergrund ist spezifisch für die Jobsteuerung in einer Shell. Es macht keinen Sinn, diese Begriffe in der Anwendung für die Prozessverwaltung im Allgemeinen zu verwenden. Im allgemeineren Kontext ist die Daemonisierung etwas, das ein Prozess für sich selbst ausführt, und die Verwendung von "subprocess.Popen" zum Starten eines solchen Prozesses ist völlig Standard. 'Python-Daemon' ist in Ordnung; Es hat eine umständliche API, aber es ist kampferprobt, und die letztgenannte Qualität ist wichtig, da es einfach ist, solche Dinge falsch zu verstehen. – Alp