Прошлой ночью я намеревался сделать это, используя канал:
import os
import subprocess
with open("test2", "w") as f:
f.write("""import time
print('start')
time.sleep(2)
print('done')""")
(readend, writeend) = os.pipe()
p = subprocess.Popen(['python3', '-u', 'test2'], stdout=writeend, bufsize=0)
still_open = True
output = ""
output_buf = os.read(readend, 1).decode()
while output_buf:
print(output_buf, end="")
output += output_buf
if still_open and p.poll() is not None:
os.close(writeend)
still_open = False
output_buf = os.read(readend, 1).decode()
Вынудить буферизовать изображение и прочитать один символ за раз (чтобы убедиться, что мы не блокируем записи изпроцесс заполнил буфер), закрывая конец записи по окончании процесса, чтобы убедиться, что чтение правильно перехватывает EOF.Посмотрев на subprocess
, оказалось, что это было немного излишним.С PIPE
вы получаете большую часть этого бесплатно, и я закончил с этим, который, кажется, работает нормально (вызывайте read столько раз, сколько необходимо, чтобы продолжить опустошение канала), просто с этим и предполагая, что процесс завершен, вам не нужно беспокоитьсяо его опросе и / или о том, что конец записи канала закрыт для корректного определения EOF и выхода из цикла:
p = subprocess.Popen(['python3', '-u', 'test2'],
stdout=subprocess.PIPE, bufsize=1,
universal_newlines=True)
output = ""
output_buf = p.stdout.readline()
while output_buf:
print(output_buf, end="")
output += output_buf
output_buf = p.stdout.readline()
Это немного меньше в «реальном времени», так как в принципестрока буферизована.
Примечание. Я добавил -u
к вашему вызову Python, поскольку вам также необходимо убедиться, что буферизация вызываемого процесса не мешает.