Однако при любом подходе графические интерфейсы в примерах 10.26 и 10.28 оказываются заблокированными на две секунды каждый раз, когда пытаются прочитать данные из канала с помощью os.popen. На практике интерфейсы становятся очень неповоротливыми — команды переместить окно, изменить его размер, перерисовать, поднять над другими окнами и так далее ожидают до двух секунд, пока сценарий командной строки не отправит данные графическому интерфейсу и тем самым не обеспечит возврат из функции чтения канала. Еще хуже то, что если щелкнуть на кнопке GO! дважды во второй версии графического интерфейса, только одно окно будет обновляться каждые две секунды, потому что графический интерфейс «застрянет» в обработчике события нажатия кнопки — он не сможет выйти из цикла чтения, пока дочерний сценарий командной строки не завершится. Завершение работы программы также выполняется не очень изящно (в окне консоли появится множество сообщений об ошибках).
Из-за этих ограничений — чтобы избежать заблокированных состояний — независимо запускаемый графический интерфейс не должен читать данные непосредственно, если могут возникать задержки в отображении. Например, в сценарии из предыдущего раздела (пример 10.25), использующем сокеты, цикл обработки событий от таймера after позволяет графическому интерфейсу проверять наличие данных вместо того, чтобы ждать их, и отображать по мере появления. Поскольку графический интерфейс не ждет, пока данные появятся, он остается активным между операциями вывода.
Конечно, истинная причина этих проблем заключается в том, что цикл чтения/записи в используемой здесь функции из модуля guiStreams слишком упрощен — ошибочное размещение операции чтения в графическом интерфейсе провоцирует блокировку. Существуют различные решения, позволяющие избежать этого.
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011