Мне нужно прочитать выходные данные дочернего процесса по мере его производства - возможно, не на каждом write
, но задолго до завершения процесса.Я пробовал решения из документов Python3 и вопросов SO здесь и здесь , но я все еще ничего не получаю, пока ребенок не завершит работу.
Приложение предназначено для мониторинга обучениямодели глубокого обучения.Мне нужно получить выходные данные теста (около 250 байт для каждой итерации с интервалом примерно в 1 минуту) и следить за статистическими сбоями.
- Я не могу изменить механизм обучения;например, я не могу вставить
stdout.flush()
в код дочернего процесса. - Я могу разумно дождаться накопления дюжины строк;Я надеялся, что заполнение буфера решит мою проблему.
Код: варианты закомментированы.
Родитель
cmd = ["/usr/bin/python3", "zzz.py"]
# test_proc = subprocess.Popen(
test_proc = subprocess.run(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT
)
out_data = ""
print(time.time(), "START")
while not "QUIT" in str(out_data):
out_data = test_proc.stdout
# out_data, err_data = test_proc.communicate()
print(time.time(), "MAIN received", out_data)
Ребенок (zzz.py)
from time import sleep
import sys
for _ in range(5):
print(_, "sleeping", "."*1000)
# sys.stdout.flush()
sleep(1)
print("QUIT this exercise")
Несмотря на отправку строк размером более 1000 байт, заполнение буфера (проверенное в другом месте как 2 КБ; здесь я поднялся до 50 КБ) не заставляет родителя «видеть» новый текст.
Чего мне не хватает, чтобы заставить это работать?
Обновление, касающееся ссылок, комментариев и опубликованного ответа iBug
:
Popen
вместо run
исправлена проблема блокировки.Каким-то образом я пропустил это в документации и моих экспериментах с обоими. universal_newline=True
аккуратно изменил возврат байтов в строку: легче обрабатывать на принимающей стороне, хотя с чередующимися пустыми строками (легко обнаружить и отбросить). - Установка
bufsize
на что-то крошечное (например, 1
) ни на что не повлияло;родитель все еще должен ждать, пока ребенок заполнит буфер stdout
, в моем случае - 8 000. export PYTHONUNBUFFERED=1
, прежде чем выполнение действительно решило проблему буферизации.Спасибо wim
за ссылку.
Если кто-то не придумает канонического, изящного решения, которое делает их устаревшими, я приму ответ iBug завтра.