Некоторые практические правила для subprocess.
- Никогда не используйте
shell=True. Он без нужды вызывает дополнительный процесс оболочки для вызова вашей программы.
- При вызове процессов аргументы передаются в виде списков.
sys.argvв Python список, и поэтому argvв С. Таким образом , вы передаете список , чтобы 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 буферизует свой вывод, когда обнаруживает, что он подключен к конвейеру, а не к терминалу. Это поведение по умолчанию - при подключении к каналу программы должны явно сбрасывать стандартный вывод для результатов в реальном времени, иначе стандартная библиотека C будет буферизована.
Чтобы проверить это, попробуйте вместо этого запустить следующее:
cmd = [sys.executable, 'test_out.py']
и создадим test_out.pyфайл с содержимым:
import sys
import time
print ("Hello")
sys.stdout.flush()
time.sleep(10)
print ("World")
Выполнение этого подпроцесса должно дать вам «Hello» и подождать 10 секунд, прежде чем дать «World». Если это происходит с кодом Python выше, а не с rsync, это означает, что он rsyncсам буферизует вывод, поэтому вам не повезло.
Решением было бы подключиться напрямую к a pty, используя что-то вроде pexpect.