Einige Faustregeln für subprocess
.
- Niemals benutzen
shell=True
. Es ruft unnötig einen zusätzlichen Shell-Prozess auf, um Ihr Programm aufzurufen.
- Beim Aufrufen von Prozessen werden Argumente als Listen weitergegeben.
sys.argv
in Python ist eine Liste, ebenso wie argv
in C. Sie übergeben also eine Liste , Popen
um Unterprozesse aufzurufen, keine Zeichenfolge.
- Leiten Sie nicht
stderr
zu a um, PIPE
wenn Sie es nicht lesen.
- Leiten Sie nicht um,
stdin
wenn Sie nicht darauf schreiben.
Beispiel:
import subprocess, time, os, sys
cmd = ["rsync.exe", "-vaz", "-P", "source/" ,"dest/"]
p = subprocess.Popen(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
for line in iter(p.stdout.readline, b''):
print(">>> " + line.rstrip())
Das heißt, es ist wahrscheinlich, dass rsync seinen Ausgang puffert, wenn es erkennt, dass es mit einer Pipe anstelle eines Terminals verbunden ist. Dies ist das Standardverhalten. Wenn eine Verbindung zu einer Pipe besteht, müssen Programme stdout explizit leeren, um Echtzeitergebnisse zu erhalten. Andernfalls wird die Standard-C-Bibliothek gepuffert.
Um dies zu testen, führen Sie stattdessen Folgendes aus:
cmd = [sys.executable, 'test_out.py']
und erstellen Sie eine test_out.py
Datei mit dem Inhalt:
import sys
import time
print ("Hello")
sys.stdout.flush()
time.sleep(10)
print ("World")
Wenn Sie diesen Unterprozess ausführen, sollten Sie "Hallo" erhalten und 10 Sekunden warten, bevor Sie "Welt" geben. Wenn dies mit dem obigen Python-Code und nicht mit passiert rsync
, bedeutet dies, dass die rsync
Ausgabe selbst gepuffert wird, sodass Sie kein Glück haben.
Eine Lösung wäre pty
, sich mit so etwas direkt mit a zu verbinden pexpect
.