Буферизация потоков ввода-вывода, вывод программы и взаимоблокировки

buferizaciya potokov vvoda vyvoda vyvod programmy i vzaimoblokirovki Сетевые сценарии

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

Например, если client1 и client4 не будут периодически выталкивать выходной буфер, как они это делают, то единственной гарантией их работы стало бы автоматическое выталкивание потоков вывода при завершении их процессов. Без выталкивания буфера вручную передача данных в client1 не производилась бы до момента завершения процесса (в этот момент все выходные данные были бы отправлены в виде единого сообщения), а данные, генерируемые функцией client4, были бы отправлены не полностью, до момента завершения

процесса (последнее выводимое сообщение задержалось бы в выходном буфере).

Еще более тонкий аспект: обе функции, client3 и client4, полагаются на то, что встроенная функция input сначала автоматически выталкивает sys.stdout, чтобы гарантировать вывод строки приглашения к вводу, и тем самым обеспечивает отправку данных, записанных в выходной буфер предыдущими вызовами функции print. Без такого неявного выталкивания буферов (или без дополнительных операций выталкивания, выполняемых вручную) функция client3 была бы немедленно за бло киро ва на. Как и client4, если из нее удалить операцию выталкивания буфера вручную (даже с учетом автоматического выталкивания буфера функцией input удаление операции выталкивания буфера из функции client4 приведет к тому, что заключительное сообщение, выводимое функцией print, не будет отправлено, пока процесс не завершится). Функция client5 проявляет те же черты поведения, что и client4, потому что она просто меняет местами процессы — ожидающий и устанавливающий соединение.

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

Мы, конечно, можем открывать файлы-обертки сокетов в не буфери- зо ван ном режиме, передав методу makefile нулевое значение во втором аргументе (как обычной функции open), однако это не позволит обертке работать в текстовом режиме, необходимом для функции print и желательном для функции input. Фактически, такая попытка открыть файл-обертку для сокета в текстовом режиме с отключенной буферизацией приведет к исключению, потому что Python 3.X больше не поддерживает небуферизованный режим для текстовых файлов (в настоящее время он допускается только для двоичных файлов). Иными словами, из-за того, что функция print требует использование текстового режима, режим буферизации для файлов потоков вывода предполагается по умолчанию. Кроме того, возможность открытия файлов-оберток для сокетов в режиме по строч ной буфери за ции, похоже, больше не поддерживается в Python 3.X (подробнее об этом рассказывается ниже).

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

Использованная литература:

Марк Лутц — Программирование на Python, 4-е издание, II том, 2011

Каталог сайтов Всего.ру
Оцените статью
Секреты программирования
Добавить комментарий