Небуферизованный вывод подпроцесса (отсутствует последняя строка)

StackOverflow https://stackoverflow.com/questions/2432556

  •  19-09-2019
  •  | 
  •  

Вопрос

Должно быть, я упускаю из виду что-то ужасно очевидное.Мне нужно выполнить программу C, отобразить ее вывод в реальном времени и, наконец, проанализировать ее последнюю строку, что должно быть простым, поскольку последняя напечатанная строка всегда одинаковый.

process = subprocess.Popen(args, shell = True,  
                           stdout = subprocess.PIPE, stderr = subprocess.PIPE)

# None indicates that the process hasn't terminated yet.
while process.poll() is None:

    # Always save the last non-emtpy line that was output by the child
    # process, as it will write an empty line when closing its stdout.
    out = process.stdout.readline()
    if out:
        last_non_empty_line = out

    if verbose:
        sys.stdout.write(out)   
        sys.stdout.flush()

# Parse 'out' here...

Однако время от времени последняя строка не печатается.Значение по умолчанию для Popens размер буфера равен 0, поэтому предполагается, что он небуферизован.Я также пытался, но безрезультатно, добавить fflush(стандартный вывод) в код C непосредственно перед выходом, но кажется, что нет абсолютно никакой необходимости очищать поток перед выходом из программы.

Есть идеи?

Это было полезно?

Решение

readline() должен буферизовать текст, ожидая новой строки.

У вас всегда будет состояние гонки — никакое количество небуферизованных потоков не сможет обработать тот факт, что вы обрабатываете строку, затем проверяете выход, а затем читаете строку, поэтому, если подпроцесс завершается, пока вы обрабатываете строку , больше ничего не прочитаешь.Кроме того, оболочка, вероятно, вводит собственную буферизацию.

Итак, вы можете:

  1. Использовать communicate() и отказаться от подробного вывода во время выполнения подпроцесса.

  2. Обязательно продолжайте чтение после завершения процесса, пока не получите EOF.

Я бы также предложил изменить ваш код, чтобы вам не приходилось использовать shell=True.

Другие советы

Проблема в том, что вы читаете строки до тех пор, пока процесс не завершится (process.poll()), хотя вы используете буферизацию из-за флага оболочки.

Вам придется продолжать чтение процесса.stdout, пока не дойдете до конца файла или пустой строки.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top