Некоторые практические правила для 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
.