Заключение в кавычки от MSDN
наконец используется, чтобы гарантировать, что блок операторов кода выполняется независимо от того, как предшествование попытка блок , вышел .
Change the stdout from the rsync process to be unbuffered.
p = subprocess.Popen(cmd,
shell=True,
bufsize=0, # 0=unbuffered, 1=line-buffered, else buffer-size
stdin=subprocess.PIPE,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE)
Некоторые практические правила для подпроцесса
.
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
.
import sys
import time
print ("Hello")
sys.stdout.flush()
time.sleep(10)
print ("World")
Выполнение этого подпроцесса должно дать вам «Hello» и подождать 10 секунд, прежде чем дать «World». Если это происходит с кодом Python выше, а не с rsync
, это означает, что сам rsync
буферизует вывод, поэтому вам не повезло.
Решением будет прямое подключение в pty
, используя что-то вроде pexpect
.
import sys
import time
print ("Hello")
sys.stdout.flush()
time.sleep(10)
print ("World")
Выполнение этого подпроцесса должно дать вам «Hello» и подождать 10 секунд, прежде чем дать «World». Если это происходит с кодом Python выше, а не с rsync
, это означает, что сам rsync
буферизует вывод, поэтому вам не повезло.
Решением будет прямое подключение в pty
, используя что-то вроде pexpect
.