Некоторые правила для 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 буферизует свой вывод, когда обнаружит, что он подключен к каналу, а не к терминалу. Это поведение по умолчанию - при подключении к каналу программы должны явно сбрасывать стандартный вывод для результатов в реальном времени, в противном случае стандартная библиотека 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
само буферизует вывод, так что вам не повезло.
Решением было бы подключиться напрямую к pty
, используя что-то вроде pexpect
.