Некоторые эмпирические правила для subprocess
.
- Никогда использование
shell=True
. Он без необходимости вызывает дополнительный процесс оболочки для вызова вашей программы.
- При вызове процессов аргументы передаются как списки.
sys.argv
в python - это список, а также argv
в C. Итак, вы передаете список в Popen
для вызова подпроцессов, а не строки.
- Не переадресовывайте
stderr
в PIPE
, когда вы его не читаете.
- Не переадресовывайте
stdin
, когда вы не пишете на него.
Пример:
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())
Тем не менее, существует вероятность того, что Rsync буферизует свой вывод, когда он обнаруживает, что он подключен к трубе вместо терминала. Это поведение по умолчанию - при подключении к каналу программы должны явно скрывать stdout для результатов в реальном времени, иначе стандартная библиотека C будет буферизоваться.
Чтобы проверить это, попробуйте запустить вместо этого:
cmd = [sys.executable, 'test_out.py']
и создать test_out.py
файл с содержимым:
import sys
import time
print ("Hello")
sys.stdout.flush()
time.sleep(10)
print ("World")
Выполнение этого подпроцесса должно дать вам «Привет» и подождите 10 секунд прежде чем давать «Мир». Если это происходит с кодом python выше, а не с rsync
, это значит, что rsync
сам является буферизирующим выходом, поэтому вам не повезло.
Решение будет заключаться в подключении непосредственно к pty
, используя что-то вроде pexpect
.
Дубликат: 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- a-sub-process-while-it-running –
(Исходя из google?) все PIPE будут заторможены, когда один из буферов PIPE будет заполнен и не будет прочитан. например stdout, когда stderr заполнен. Никогда не пропускайте PIPE, которую вы не собираетесь читать. –
Может кто-нибудь объяснить, почему вы не можете просто установить stdout в sys.stdout вместо subprocess.PIPE? – Mike