Starten Sie einen völlig unabhängigen Prozess

Lesezeit: 5 Minuten

Starten Sie einen vollig unabhangigen Prozess
Garfield

Ich möchte einen Prozess aus meinem Python-Skript initiieren main.py. Insbesondere möchte ich den folgenden Befehl ausführen:

`nohup python ./myfile.py &`

und die Datei myfile.py sollte weiterlaufen, auch nach dem main.py Skript beendet.

Ich möchte auch die bekommen pid des neuen Prozesses.

Ich habe es versucht:

  • os.spawnl*
  • os.exec*
  • subprocess.Popen

und alle beenden die myfile.py wenn das main.py Skript beendet.


Aktualisieren: Kann ich benutzen os.startfile mit xdg-open? Ist es der richtige Ansatz?


Beispiel

a = subprocess.Popen([sys.executable, "nohup /usr/bin/python25 /long_process.py &"],
     stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
print a.pid

Wenn ich es überprüfe ps aux | grep long_process, es wird kein Prozess ausgeführt.

long_process.py die weiterhin Text druckt: kein Ausgang.

Mache ich hier etwas falsch?

  • Können Sie ein Minimalbeispiel posten, das nicht funktioniert? Nach einem trivialen python -c 'import subprocess; subprocess.Popen(["sleep", "60"])' die Ausgabe von ps zeigt, dass die sleep läuft gut weiter, nachdem Python beendet wurde.

    – Benutzer4815162342

    23. Dezember 2014 um 17:15 Uhr


  • Sie führen Python mit einem einzigen Argument aus, "nohup /usr/bin/python25 ...", was nicht funktionieren kann, weil die python Ausführbare Datei sucht nach einem Skript in einer Datei mit dem genauen Namen nohup /usr/bin/..., die es nicht gibt. Und da Sie angeben stderr wie PIPE ohne jemals den Inhalt der Pipe zu lesen, bekommen Sie die Fehlermeldung nie zu sehen. Verliere die nohup und &, und einfach laufen subprocess.Popen([sys.executable, "/.../long_process.py"]). Auch nicht angeben stdin und stderr als Rohre, es sei denn, Sie meinen es so.

    – Benutzer4815162342

    23. Dezember 14 um 17:21 Uhr


  • nohup am sinnvollsten, wenn Sie einen Prozess von einer Shell aus starten. Ich sehe nicht shell=True in deinem Popen Anruf.

    – 9000

    23. Dezember 14 um 17:42 Uhr

1642931166 903 Starten Sie einen vollig unabhangigen Prozess
9000

Sie öffnen Ihren lang andauernden Prozess und halten Sie eine Pfeife dazu. Sie erwarten also, mit ihm zu sprechen. Wenn Ihr Launcher-Skript beendet wird, können Sie nicht mehr mit ihm sprechen. Der lang andauernde Prozess erhält a SIGPIPE und Ausgänge.

Folgendes hat nur für mich funktioniert (Linux, Python 2.7).

Erstellen Sie eine lang laufende ausführbare Datei:

$ echo "sleep 100" > ~/tmp/sleeper.sh

Führen Sie Python REPL aus:

$ python
>>>

import subprocess
import os
p = subprocess.Popen(['/bin/sh', os.path.expanduser('~/tmp/sleeper.sh')])
# look ma, no pipes!
print p.pid
# prints 29893

Beenden Sie die REPL und sehen Sie, wie der Prozess noch läuft:

>>> ^D
$ ps ax | grep sleeper
29893 pts/0    S      0:00 /bin/sh .../tmp/sleeper.sh
29917 pts/0    S+     0:00 grep --color=auto sleeper

Wenn Sie zuerst mit dem gestarteten Prozess kommunizieren und ihn dann alleine weiterlaufen lassen möchten, haben Sie einige Möglichkeiten:

  • Handhaben SIGPIPE Sterben Sie in Ihrem lang andauernden Prozess nicht daran. Live ohne stdin, nachdem der Launcher-Prozess beendet wurde.
  • Übergeben Sie alles, was Sie wollten, mit Argumenten, Umgebung oder einer temporären Datei.
  • Wenn Sie eine bidirektionale Kommunikation wünschen, sollten Sie die Verwendung einer benannten Pipe (Mann mkfifo) oder einen Socket oder das Schreiben eines richtigen Servers.
  • Verzweigen Sie den lang andauernden Prozess, nachdem die anfängliche bidirektionale Kommunikationsphase abgeschlossen ist.

  • Tolle Antwort, es ist ein guter Punkt, an dem der Prozess stirbt SIGPIPE. (Im Code aus der Frage wurde der Prozess nie gestartet, aber das OP hat möglicherweise auch andere Varianten ausprobiert, die gestartet wurden und aufgrund von gestorben sind SIGPIPE.)

    – Benutzer4815162342

    23. Dezember 2014 um 19:50 Uhr

  • Es entsteht kein “völlig unabhängiger Prozess” (das was python-daemon Paket tut). Außerdem wird ein untergeordneter Prozess SIGPIPE in Python 2 nicht erhalten. In einfachen Fällen reicht Ihre Lösung jedoch aus (Sie sollten auf os.devnull stdin/stdout/stderr des Kindes, um das Warten auf Eingaben und/oder eine falsche Ausgabe an das Terminal zu vermeiden).

    – jfs

    23. Dezember 2014 um 20:35 Uhr

  • @ user4815162342: Es stirbt nicht aufgrund von SIGPIPE in Python 2 (die Frage hat das Tag python2.7).

    – jfs

    23. Dezember 14 um 20:37 Uhr


  • Hier ist ein Beispiel dafür, warum die Umleitung wichtig ist: Sie kann es einem übergeordneten Prozess ermöglichen, sich zu beenden, bevor sein untergeordneter Prozess seine Ausgabe fertig geschrieben hat: Python subprocess .check_call vs .check_output

    – jfs

    14. November 20 um 6:22 Uhr

Sie können verwenden os.fork().

import os
pid=os.fork()
if pid==0: # new process
    os.system("nohup python ./myfile.py &")
    exit()
# parent process continues

  • Beachten Sie, dass os.fork() existiert nicht für Windows

    – Pro Q

    13. Oktober 18 um 8:34 Uhr

  • Verwenden nohup hier ist sinnlos. Es macht genau zwei Dinge: (1) Deaktivieren der HUP-Weitergabe, das heißt schon für nicht interaktive Shells deaktiviert und muss daher nicht weiter deaktiviert werden; und (2) stdin, stdout und stderr umleiten, wenn sie an das Terminal angeschlossen sind (was Sie trivial selbst tun können; </dev/null >nohup.out 2>&1 und Sie haben genau die gleichen Umleitungen gemacht, die nohup machen würde). Es ist viel effizienter, alle Schalen ganz wegzulassen, wie es die Antwort von @jfs tut.

    – Charles Duffy

    19. Januar 21 um 1:47 Uhr


1642931166 709 Starten Sie einen vollig unabhangigen Prozess
jfs

Ich konnte keinen laufenden Prozess sehen.

Sie sehen keinen laufenden Prozess, weil das Kind python Der Prozess wird sofort beendet. Der Popen Argumente sind falsch, wie user4815162342 im Kommentar sagt.

Zum Starten eines völlig unabhängig Prozess, den Sie verwenden könnten python-daemon Paket oder verwenden Sie systemd/supervisord/etc:

#!/usr/bin/python25
import daemon
from long_process import main

with daemon.DaemonContext():
    main()

Obwohl es in Ihrem Fall ausreichen könnte, das Kind mit dem Richtigen zu beginnen Popen Argumente:

with open(os.devnull, 'r+b', 0) as DEVNULL:
    p = Popen(['/usr/bin/python25', '/path/to/long_process.py'],
              stdin=DEVNULL, stdout=DEVNULL, stderr=STDOUT, close_fds=True)
time.sleep(1) # give it a second to launch
if p.poll(): # the process already finished and it has nonzero exit code
    sys.exit(p.returncode)

Wenn der untergeordnete Prozess dies nicht erfordert python2.5 dann könntest du verwenden sys.executable stattdessen (um dieselbe Python-Version wie die übergeordnete zu verwenden).

Hinweis: Der Code wird geschlossen DEVNULL im Elternprozess, ohne auf das Ende des Kindprozesses zu warten (es hat keine Auswirkung auf das Kind).

.

602410cookie-checkStarten Sie einen völlig unabhängigen Prozess

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy