Деякі емпіричні правила для 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 буферизує свій вихід, коли виявляє, що він підключений до труби замість терміналу. Це поведінка за замовчуванням - при підключенні до каналу програми повинні явно змивати 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
.