Несмотря на некоторые незначительные недостатки, реализация графических интерфейсов на основе потоков/очередей/каналов имеет весьма широкую область применения. Для иллюстрации приведем еще один короткий пример использования. Ниже демонстрируется запуск простого сценария в окне консоли, который каждые две секунды выводит все более и более длинную строку:
C:\…\PP4E\Gui\Tools> type spams.py
import time
for i in range(1, 10, 2):
time.sleep(2) # выводит текст в стандартный поток вывода
print(‘spam’ * i) # GUI ничего не знает об этом, ведь так?
C:\…\PP4E\Gui\Tools> python spams.py spam
spamspamspam
spamspamspamspamspam
spamspamspamspamspamspamspam
spamspamspamspamspamspamspamspamspam
Попробуем завернуть этот сценарий в графический интерфейс, введя программный код в интерактивной оболочке, для разнообразия. Следующий фрагмент импортирует новую версию функции перенаправления потока вывода в графический интерфейс как библиотечный компонент и с ее помощью создает окно, в котором отображаются пять строк, выводимые сценарием каждые две секунды — так же, как в окне консоли, — за которыми следует строка <end>, отражающая момент завершения дочерней программы. Получившееся окно изображено на рис. 10.16:
C:\…\PP4E\Gui\Tools> python
>>> from tkinter import Tk
>>> from pipe_gui3 import redirectedGuiShellCmd
>>> root = Tk()
>>> redirectedGuiShellCmd(‘python -u spams.py’, root)
Рис. 10.16. Графический интерфейс, отображающий полученный по каналу вывод другой программы
Когда дочерняя программа завершится, поток-производитель в примере 10.29 определит признак конца файла и поместит в очередь заключительную пустую строку. В ответ на это цикл обработки событий от таймера выведет строку <end> в окно. В данном случае программа завершается обычным образом без вывода каких-либо сообщений, но в других ситуациях нам может потребоваться добавить логику завершения, чтобы подавить вывод сообщений об ошибках. Обратите внимание, что здесь, как и прежде, дочерняя программа имитирует выполнение продолжительных операций с помощью функции sleep, а кроме того, нам необходимо использовать ключ —u, чтобы запретить буферизацию стандартного потока вывода, — без этого в течение восьми секунд в графическом интерфейсе ничего отображаться не будет, пока дочерняя программа не завершит работу. При наличии ключа графический интерфейс будет получать и отображать строки по мере их вывода, каждые две секунды.
Наконец, такой программный код, не использующий сокеты, не требующий вносить изменения в оригинальную программу и не блокирующий графический интерфейс, можно было бы использовать для отображения вывода программ командной строки в графическом интерфейсе. Конечно, во многих случаях может оказаться слишком сложным добавлять графический интерфейс таким способом, и для вас может оказаться проще превратить свой сценарий в традиционную программу с графическим интерфейсом, у которой есть главное окно и цикл событий. Кроме того, графические интерфейсы, которые мы реализовали в этом разделе, мы обязали просто отображать вывод другой программы, тогда как на практике от графического интерфейса может требоваться нечто большее. Однако для многих программ отделение представления от реализации, которое обеспечивает модель графического интерфейса, порождающего дочернюю программу командной строки, имеет свои преимущества — обе части приложения понять будет намного проще, если они не будут смешиваться.
Сокеты мы будем подробно рассматривать в следующей части книги, поэтому данное обсуждение следует рассматривать, как предварительное знакомство. Как мы увидим далее, все станет еще более интересным, как только мы начнем комбинировать графические интерфейсы, потоки выполнения и сокеты.
В следующей главе мы закончим обсуждение тем, касающихся исключительно графического интерфейса, где рассмотрим применение уже знакомых нам виджетов и приемов для реализации более практичных программ. Но перед этим в следующем разделе мы познакомимся с некоторыми крупными примерами графических интерфейсов, рассмотрев сценарии, которые запускают их автоматически и могут служить образцами, демонстрирующими возможности языка Python и библиотеки tkinter.
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011