Ich versuche, ein Shell-Skript auf die viel besser lesbare Python-Version zu portieren. Das ursprüngliche Shell-Skript startet mehrere Prozesse (Dienstprogramme, Monitore, etc.) im Hintergrund mit "&". Wie kann ich den gleichen Effekt in Python erreichen? Ich möchte, dass diese Prozesse nicht absterben, wenn die Python-Skripte beendet sind. Ich bin mir sicher, dass es irgendwie mit dem Konzept eines Daemons zusammenhängt, aber ich konnte nicht herausfinden, wie man das einfach machen kann.
Antworten
Zu viele Anzeigen?Beide erfassen die Ausgabe und laufen im Hintergrund mit threading
Wie erwähnt zu dieser Antwort wenn Sie die Ausgabe mit stdout=
und versuchen dann read()
dann wird der Prozess blockiert.
Es gibt jedoch Fälle, in denen Sie dies benötigen. Ich wollte zum Beispiel zwei Prozesse, die über einen Port miteinander kommunizieren und speichern ihr stdout in einer Protokolldatei und stdout.
Die threading
Modul erlaubt uns das zu tun.
Schauen Sie sich zunächst an, wie Sie den Teil der Ausgabeumleitung in dieser Frage allein durchführen können: Python Popen: Gleichzeitig nach stdout UND in die Protokolldatei schreiben
Dann:
main.py
#!/usr/bin/env python3
import os
import subprocess
import sys
import threading
def output_reader(proc, file):
while True:
byte = proc.stdout.read(1)
if byte:
sys.stdout.buffer.write(byte)
sys.stdout.flush()
file.buffer.write(byte)
else:
break
with subprocess.Popen(['./sleep.py', '0'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc1, \
subprocess.Popen(['./sleep.py', '10'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc2, \
open('log1.log', 'w') as file1, \
open('log2.log', 'w') as file2:
t1 = threading.Thread(target=output_reader, args=(proc1, file1))
t2 = threading.Thread(target=output_reader, args=(proc2, file2))
t1.start()
t2.start()
t1.join()
t2.join()
schlaf.py
#!/usr/bin/env python3
import sys
import time
for i in range(4):
print(i + int(sys.argv[1]))
sys.stdout.flush()
time.sleep(0.5)
Nach dem Laufen:
./main.py
stdout wird alle 0,5 Sekunden für jeweils zwei Zeilen aktualisiert:
0
10
1
11
2
12
3
13
und jede Protokolldatei enthält das jeweilige Protokoll für einen bestimmten Prozess.
Inspiriert durch: https://eli.thegreenplace.net/2017/interacting-with-a-long-running-child-process-in-python/
Getestet auf Ubuntu 18.04, Python 3.6.7.
Wahrscheinlich möchten Sie zunächst das os-Modul zum Forken verschiedener Threads untersuchen (indem Sie eine interaktive Sitzung öffnen und help(os) aufrufen). Die relevanten Funktionen sind fork und eine der exec-Funktionen. Um Ihnen eine Idee zu geben, wie Sie beginnen können, fügen Sie etwas wie das Folgende in eine Funktion ein, die das Forking durchführt (die Funktion muss eine Liste oder ein Tupel 'args' als Argument nehmen, das den Namen des Programms und seine Parameter enthält; Sie möchten vielleicht auch stdin, out und err für den neuen Thread definieren):
try:
pid = os.fork()
except OSError, e:
## some debug output
sys.exit(1)
if pid == 0:
## eventually use os.putenv(..) to set environment variables
## os.execv strips of args[0] for the arguments
os.execv(args[0], args)
- See previous answers
- Weitere Antworten anzeigen