Niektóre zasady dla subprocess
.
- Nigdy użycie
shell=True
. Niepotrzebnie wywołuje dodatkowy proces powłoki, aby wywołać twój program.
- Podczas wywoływania procesów argumenty są przekazywane jako listy.
sys.argv
w pythonie to lista, podobnie jak argv
w C. Tak więc przekazujesz listę do Popen
, aby wywołać podprocesy, a nie ciąg.
- Nie przekierowuj
stderr
do PIPE
, gdy jej nie czytasz.
- Nie przekierowuj
stdin
, gdy nie piszesz do niego.
przykład:
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())
Niemniej, jest prawdopodobne, że bufory tworzenia serwerów swoją moc, gdy wykryje, że jest podłączony do rury, a nie gniazda. Jest to zachowanie domyślne - po podłączeniu do potoku, programy muszą jawnie przepuszczać standardowe wyjście dla wyników w czasie rzeczywistym, w przeciwnym razie standardowa biblioteka C będzie buforować.
Aby przetestować za to, spróbuj uruchomić ten zamiast:
cmd = [sys.executable, 'test_out.py']
i utworzyć plik test_out.py
z treścią:
import sys
import time
print ("Hello")
sys.stdout.flush()
time.sleep(10)
print ("World")
wykonujących to podproces powinno dać "Hello" i odczekaj 10 sekund przed podaniem "Świata". Jeśli dzieje się to z powyższym kodem Pythona, a nie z rsync
, oznacza to, że samo rsync
buforuje wynik, więc nie masz szczęścia.
Rozwiązaniem byłoby połączenie bezpośrednio z pty
, używając czegoś takiego jak pexpect
.
Duplikat: http://stackoverflow.com/questions/1085071/real-time-intercepting-of-stdout-from-another-process-in-python, http://stackoverflow.com/questions/ 874815/how-do-i-get-real-time-information-back-from-a-subprocess-popen-in-python-2-5, http://stackoverflow.com/questions/527197/intercepting-stdout- of-a-subprocess-while-it-is-is-running –
(Z Google?) wszystkie PIPE zakleszczą się, gdy jeden z buforów PIPE zostanie wypełniony i nie zostanie odczytany. na przykład stdout, kiedy stderr jest wypełniony. Nigdy nie przepuszczaj PIPE, którego nie zamierzasz czytać. –
Czy ktoś mógłby wyjaśnić, dlaczego nie można po prostu ustawić stdout na sys.stdout zamiast subprocess.PIPE? – Mike