Подтвердить что ты не робот

Принудительный запуск другого стандартного программного обеспечения без использования буфера Python

Python script управляет внешним приложением в Linux, передавая входные данные через канал во внешние приложения stdin и считывая выходные данные через канал из внешнего приложения stdout.

Проблема заключается в том, что записи в каналы буферизуются блоком, а не по строке, и поэтому задержки возникают до того, как управляющий script получает данные, выводимые, например, printf во внешнем приложении.

Внешнее приложение не может быть изменено для добавления явных вызовов fflush (0).

Как можно использовать pty модуль стандартной библиотеки python с subprocess для этого?

4b9b3361

Ответ 1

Вы можете использовать PTY, чтобы решить эту проблему:

  • Создание пары pty master/slave;
  • Подключение дочернего процесса stdin, stdout и stderr к ведомому устройству pty;
  • Чтение и запись в master файл pty в родительском.

Ответ 2

Выполнение этого возможно, но единственное решение, о котором я могу думать, довольно запутанное, не переносное и, вероятно, чревато проблематичными деталями. Вы можете использовать LD_PRELOAD, чтобы заставить внешнее приложение загружать динамическую библиотеку, которая содержит конструктор, который вызывает setvbuf для unbuffer stdout. Вероятно, вы также захотите обернуть setvbuf в библиотеке, чтобы приложение явно не буферизовало свой собственный stdout. И вы захотите обернуть fwrite и printf, чтобы они смывались при каждом вызове. Запись .so для предварительной загрузки приведет вас за пределы python.

Ответ 3

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

Обратите внимание на то, что у хорошо установленной команды, такой как file, есть опция (-n), которая заставляет ее явно скрывать свой вывод, Это необходимо при использовании файла в режиме, в котором он считывает имена входных файлов из канала и печатает обнаруженный тип. Поскольку в этом режиме программа файлов не завершается, результат не будет отображаться иначе.

Рассмотрим это на более низком уровне: буферизация вывода просто означает, что выполнение write() в буферизованном потоке копирует данные в буфер памяти в памяти, пока буфер не заполнится или (обычно) до тех пор, пока не будет найден перевод строки. Затем часть буфера до переполнения или перевода строки записывается write() n в базовый дескриптор файла системного уровня (который может быть файлом, трубой, сокетом и т.д.).

Я не понимаю, как вы собираетесь убедить эту программу сбросить свой буфер снаружи.

Ответ 4

Стоит отметить, что некоторые программы только буферизуют свой вывод, когда думают, что он не будет "реальным пользователем" (т.е. tty). Когда они обнаруживают, что их вывод считывается другой программой, они буферизуются.

Эмуляция tty является одной из вещей, которые Expect делает для автоматизации других процессов.

Существует чистая реализация Python Expect, но я не знаю, насколько хорошо она обрабатывает эмуляцию tty.

Ответ 6

Этот вопрос немного стар, но я думаю, что теперь ваша проблема может быть решена с помощью подпроцесса для вызова stdbuf с помощью команды, которую вы хотите выполнить exec.

Ответ 7

как os.read(stdout.fileno(), 1024) может быть полезным

Ответ 8

Попробуйте использовать интерпретатор Python с аргументом -u:

python -u myscript.py

Это заставляет Python использовать небуферизованный stdin/stdout, который может вам помочь.