На этом завершается часть данной книги, посвященная графическим интерфейсам, но рассказ о графических интерфейсах на этом не заканчивается. Если вам необходимы дополнительные знания о графических интерфейсах, посмотрите примеры использования tkinter, которые будут встречаться дальше в книге и описаны в начале этой главы. PyMailGUI, PyCalc, а также внешние примеры PyForm и PyTree — все они представляют собой дополнительные примеры реализации графических интерфейсов. В следующей части книги мы также узнаем, как создавать интерфейсы пользователя, выполняемые в веб-броузерах, — совершенно другая идея, но еще один вариант конструирования простых интерфейсов.
Имейте в виду, что даже если ни один из рассмотренных в этой книге примеров графического интерфейса не похож на тот, который вам нужно запрограммировать, тем не менее вам уже были представлены все необходимые конструктивные элементы. Создание более крупного графического интерфейса для вашего приложения в действительности заключается в иерархическом расположении составляющих его виджетов, представленных в этой части книги.
Например, сложный интерфейс может быть реализован в виде совокупности радиокнопок, списков, ползунков, текстовых полей, меню и других виджетов, располагаемых во фреймах или в сетках для получения требуемого внешнего вида. Сложный графический интерфейс может быть дополнен всплывающими окнами верхнего уровня, а также независимо выполняемыми программами с графическим интерфейсом, связь с которыми поддерживается через механизмы взаимодействий между процессами (IPC), такими как каналы, сигналы и сокеты.
Кроме того, крупные компоненты графического интерфейса могут быть реализованы в виде классов Python, прикрепляемых или расширяемых всюду, где требуется аналогичный инструмент интерфейса, — важным примером таких компонентов может служить редактор PyEdit и его использование в PyView и PyMailGUI. Подойдите к делу творчески, и набор виджетов tkinter и Python обеспечит вам практически неограниченное число структур.
Помимо данной книги, посмотрите также документацию по библиотеке tkinter, представленную в главе 7, и книги, перечисленные на сайте Python http://www.python.org и в Интернете в целом. Наконец, если мне удалось вас увлечь библиотекой tkinter, еще раз хочу порекомендовать загрузить пакеты, о которых было сказано в главе 7, особенно Pmw, PIL, Tix и ttk (в настоящее время Tix и ttk входят в состав стандартной библиотеки), и поэкспериментировать с ними. Такие инструменты наращивают мощь арсенала tkinter, позволяя создавать более сложные графические интерфейсы за счет небольшого объема программного кода
такое явление, как «сны на Python» (попробуйте дать упрощенную
Понятия «клиент» и «сервер» будут разъяснены в части книги, посвященной приложениям для Интернета. Там взаимодействие будет организовано с помощью сокетов (с которыми мы встретимся далее в этой главе и которые грубо можно назвать двунаправленными каналами связи между программами, выполняющимися на компьютерах, соединенных сетью, или на одном и том же компьютере), но модель обмена информацией в целом остается схожей. Именованные каналы (fifo), описываемые ниже, лучше соответствуют модели клиент/сервер, поскольку доступ к ним может осуществляться произвольными, несвязанными процессами (выполнять ветвление при этом не требуется). Но как мы увидим, модели сокетов повсеместно используются большинством протоколов сценариев для Интернета — сообщения электронной почты, например, являются, по сути, всего лишь форматированными строками, передаваемыми между программами через сокеты со стандартными номерами портов, зарезервированными для протоколов обмена электронной почтой.
Сходная проблема, связанная с функцией print, описывается в главе 14, где предлагается обходное решение, позволяющее предотвратить аварийное завершение программы в случае вывода трассировочной информации в поток стандартного вывода порожденными программами. В отличие от проблемы, описываемой здесь, та проблема, похоже, не связана с выводом символов Юникода, которые могут оказаться непечатаемыми в окне командной оболочки, а отражает еще один недостаток механизма вывода в стандартный поток вывода в версии Python 3.1, который может быть исправлен к моменту, когда вы будете читать эти строки. Смотрите также описание переменной окружения PYTHONIOENCODING, с помощью которой можно переопределить кодировку, используемую по умолчанию для стандартного потока вывода.
Необходимо отметить, что эту историю я рассказывал еще во втором издании книги, которое вышло в 2000 году. За последние десять лет гибкие диски практически закончили путь, который уже прошли параллельные порты и динозавры. Кроме того, запись CD или DVD выполняется не так долго, как прежде; в настоящее время появились новые возможности, такие как флешки огромного объема, беспроводные сети и даже простая электронная почта; и, естественно, у меня дома теперь стоят более совершенные компьютеры. А что касается моих детей — некоторые из них уже выросли (хотя и сохранили некоторую обратную совместимость с ними прежними).
Как оказывается, команды zip, gzip и tar также можно заменить программным кодом на языке Python. В стандартной библиотеке имеется модуль gzip, который предоставляет инструменты чтения и записи файлов gzip, имена которых обычно имеют расширение .gz. Он служит в Python общим эквивалентом стандартных утилит командной строки gzip и gunzip. Этот встроенный модуль в свою очередь использует модуль zlib, в котором реализовано gzip-совместимое сжатие данных. В последних версиях Python присутствуют также модуль zipfile для обработки архивов в формате ZIP (zip — это формат архивных файлов и сжатия, а gzip — это алгоритм сжатия) и модуль tarfile, позволяющий сценариям работать с tar-архивами. Подробности ищите в руководстве по библиотеке Python.
Это случается. Действительно, почти все, кто проводит в киберпространстве значительное время, могут рассказать пару ужасных историй. Моя состоит в следующем: несколько лет тому назад я пользовался услугами провайдера, который полностью отключился от Интернета на несколько недель из-за проникновения в систему защиты бывшего служащего. Что еще хуже, персональная электронная почта не просто не работала, но накапливавшиеся сообщения были утеряны навсегда. Если ваше существование зависит от электронной почты и Веб в такой же мере, как мое, вы хорошо представляете, какую панику может вызвать подобное отключение.
Среди разработчиков, проведших в гетто Unix достаточное время, операция поиска в файлах часто носит разговорное название «grepping».
Термин «набор графических элементов» означает объекты, используемые для создания привычных элементов интерфейса «укажи-и-щелкни» — кнопок, ползунков, полей ввода и так далее. В библиотеке tkinter определяются классы Python, соответствующие всем графическим элементам, к которым вы привыкли в графических интерфейсах. Помимо графических элементов в tkinter присутствуют "также инструменты для решения иных задач, таких как планирование событий, ожидание появления данных в сокетах и так далее.
В данной книге «Windows» относится к интерфейсу Microsoft Windows, распространенному на PC, а «X Window» относится к интерфейсу X11, чаще всего встречающемуся на платформах Unix и Linux. Эти два интерфейса в целом привязаны к платформам Microsoft и Unix (и Unix-подобным), соответственно. Существует возможность выполнения X Window поверх операционной системы Microsoft и эмуляции Windows в Unix и Linux, но эта возможность используется достаточно редко. Чтобы добавить туману, замечу, что Mac OS X обеспечивает поддержку tkinter в X Window и в родной графической подсистеме Aqua, в дополнение к платформозависимой поддержке cocoa (хотя обычно особенности OS X не слишком выделяются в коктейле Unix-подобных систем).
Формально вызов mainloop возвращает управление сценарию только после выхода из цикла событий. Обычно это происходит при закрытии главного окна, но может случиться и в ответ на явный вызов метода quit, который завершает вложенный цикл событий, но оставляет окно открытым. Почему это имеет значение, вы узнаете в главе 8.
Совет: Как уже предлагалось выше, при вводе программного кода, использующего библиотеку tkinter, в интерактивной оболочке, вам может не потребоваться вызывать функцию mainloop, чтобы отобразить виджеты. Это необходимо делать в текущей версии IDLE, но в простом интерактивном сеансе, запущенном в окне консоли, этого может не потребоваться. В любом случае управление будет возвращено интерактивной оболочке, как только вы закроете созданное окно. Примечательно, что если явно создать виджет главного окна вызовом конструктора Tk() и присоединить к нему виджеты (как описывается ниже), вам придется вызвать его снова после закрытия окна, иначе окно приложения не появится.
Если рассмотреть главный файл tkinter в библиотеке исходного программного кода Python (в настоящее время Lib\tkinter\__init__.py), можно заметить, что имена модулей, не предназначенных для экспорта, начинаются с одного символа подчеркивания. Python не копирует такие имена при обращении к модулю в операторе from в формате *. Модуль с константами называется constants.py и находится в том же самом каталоге пакета, хотя с течением времени имя и местоположение его может измениться’
В действительности именованные аргументы впервые появились в Python, чтобы сделать более очевидными такие вызовы tkinter. Внутри интерпретатора именованные аргументы передаются как словарь (который можно получить, указав аргумент вида **name в инструкции def объявления функции), поэтому обе схемы аналогичны по реализации. Но они отличаются количеством символов, которые нужно ввести и проверить.
Бывшим программистам на языке Tcl, возможно, будет интересно узнать, что Python не только внутренне строит дерево виджетов, но и использует его для автоматического создания строк путей к виджетам, которые приходится вручную писать в Tcl/Tk (например, .panel.row.cmd). Python использует адреса объектов классов виджетов, помещает их в компоненты пути и сохраняет полученные пути в дереве виджетов. Например, метке, прикрепленной к контейнеру, может быть присвоено внутреннее имя, такое как .8220096.8219408. Однако вас это не должно волновать. Просто создавайте и связывайте объекты графических элементов, передавая их родителей, и предоставьте Python самому работать с путями, опираясь на дерево объектов. Дополнительные сведения об отношениях Tk и tkinter приводятся в конце главы.
Технически после изменения размеров окна этапы добавления просто выполняются заново. Но поскольку это означает, что для графических элементов, добавляемых последними, останется недостаточно места, это равносильно тому, что элементы, добавленные последними, обрезаются первыми.
Если заглянуть в исходные тексты модуля tkinter (главным образом в файл __init__.py в каталоге Lib\tkinter), можно заметить, что многие из создаваемых им имен атрибутов начинаются с одного символа подчеркивания, что делает их уникальными; другие имена — нет, поскольку они могут быть полезны за пределами реализации tkinter (например, self.master, self. children). Странно, но библиотека tkinter по-прежнему не использует трюк с «псевдочастными» атрибутами Python, имена которых начинаются с двух символов подчеркивания, что влечет за собой автоматическое добавление имени содержащего их класса и локализации для создающего класса. Если библиотека tkinter будет когда-нибудь переписана так, чтобы использовать эту особенность, конфликты имен в подклассах виджетов будут происходить гораздо реже. Большинство атрибутов классов виджетов являются методами, предназначенными для использования в клиентских сценариях; имена, начинающиеся с одного символа подчеркивания, могут использоваться тоже, но при этом вероятность конфликтов имен все-таки ниже.
Всемирно известный производитель товаров для детского творчества, в том числе цветных карандашей, красок, мелков, фломастеров и пр. — Прим. ред.
Видимо, у автора установлены какие-то дополнительные драйверы от производителя мыши. В стандартной поставке Windows такая настройка отсутствует. — Прим. ред.
Исторический анекдот: в устаревшей в данное время версии tkinter, поставлявшейся с Python 1.3, можно было также устанавливать и извлекать значения переменных, обращаясь к ним как к функциям с аргументами или без (например, var(value) и var()). В настоящее время вместо этого нужно вызывать методы set и get переменных. По неустановленным причинам функциональная форма вызова прекратила работать годы назад, хотя ее все еще можно встретить в старом программном коде на языке Python (и в первых изданиях, по крайней мере, одной книги по языку Python, выпущенной издательством O’Reilly). Если исправление, выполненное из эстетических соображений, приводит к неработоспособности существующего программного кода, можно ли его считать исправлением?
Как будет показано дальше, exec может представлять опасность, если выполняет строки, полученные от пользователей или по сети. Это не относится к жестко определенным строкам в данном примере.
Не я автор данной картинки — она появилась в качестве баннера на сайтах для разработчиков, таких как slashdot.com, когда в 1999 году вышло первое издание «Learning Python». Она породила такую волну возмущения приверженцев Perl, что издательство O’Reilly в конце концов было вынуждено убрать эту рекламу. Хотя возможно, именно поэтому она оказалась в этой книге.
Использована цитата из фильма Стенли Кубрика «Сияние». — Прим. ред.
О технике анимации рассказывается в конце данного обзора. Поскольку в область отрисовки холста можно встраивать другие виджеты, собственная координатная система делает холсты идеальными инструментами для реализации графических интерфейсов, дающих пользователям возможность создания других графических интерфейсов путем перетаскивания встроенных виджетов по холсту — весьма полезное применение холста, которое мы изучили бы в этой книге, будь у меня несколько сотен лишних страниц.
Я решил обратить ваше внимание на это, поскольку считаю, что понимание опасности позволит в будущем избежать ее — если процесс Python обладает правом удаления файлов, передача функции eval строки с программным кодом import (‘os’ ). system(‘ rm —rf *’) в Unix приведет к вызову команды
оболочки, которая удалит все файлы в текущем каталоге и во вложенных в него подкаталогах (в Windows аналогичный эффект можно получить с помощью команды ‘rmdir /S /Q .’). Не делайте этого! Чтобы увидеть менее опасное и более полезное применение этой особенности, введите выражение __import__(‘math’).pi в одну из ячеек таблицы — щелчок на кнопке Sum вычислит значение pi (3.14159). Также безопасно будет передать функции eval выражение “__import__(‘os’).system(‘dir’)” в интерактивном сеансе. Все вышесказанное относится и к встроенной функции exec — функция eval выполняет строки выражений, функция exec — инструкции, а выражения являются инструкциями (но не наоборот). Разумеется, обычный пользователь графического интерфейса едва ли введет подобный программный код случайно, особенно если этот пользователь вы сами, но будьте внимательны!
Игра-симулятор пинг-понга, появившаяся в 1972 году и ставшая прародительницей таких известных игр, как Breakout и Arkanoid. — Прим. перев.
Самая известная, пожалуй, компания Eve Online по производству игровых программ использует Python для создания сценариев и значительной доли функциональности — не только для серверной, но и для клиентской части. Она использует версию Stackless Python, чтобы обеспечить высокую отзывчивость интерфейса при большом количестве параллельно выполняющихся заданий. Из других известных компаний, использующих Python, можно назвать производителя игры Civilization IV и ныне несуществующую Origin Systems (в последних сообщениях говорилось, что их игра Ultima Online II должна была использовать Python для поддержки анимации).
Имеется в виду модель автомобиля «Chevrolet Camaro», пользующаяся славой надежного и неприхотливого автомобиля. — Прим. перев.
Названия всех крупных примеров этой книги начинаются с приставки «Py». Это — соглашение, принятое в мире Python. Если покопаться на сайте http://www.python.org, можно найти другое свободно распространяемое программное обеспечение, следующее этой схеме именования: PyOpenGL (интерфейс к графической библиотеке OpenGL для языка Python), PyGame (набор инструментов для разработки игровых программ на языке Python) и многие другие. Я не знаю, с кого это началось, но эта схема оказалась достаточно «Пи-кантным» способом рекламы языка программирования для всего мира программного обеспечения с открытыми исходными текстами. Если Питонист слишком прямолинеен — это не Питонист!
Интересно отметить, что даже текстовый редактор IDLE в Python 3.1 страдает от тех же двух ошибок, описываемых здесь и ликвидированных в текущей версии PyEdit, — IDLE в версии 3.1 вставляет содержимое файла при открытии начиная со второй строки, а его операция поиска во внешних файлах (напоминающая диалог Grep в PyEdit) вызывает крах в результате ошибки декодирования при просмотре стандартной библиотеки Python, что вызывает аварийное завершение IDLE. Здесь вполне уместно вспомнить поговорку про сапожника без сапог…
To Be Done — что еще можно сделать. — Прим. ред.
Здесь игра слов: имя метода pack_forget дословно означает «забыть, что был скомпонован». — Прим. перев.
В ноябре 2010 года вышла версия NumPu 1.5.1 для Python 3.1. — Прим. перев.
Кроме этого следует учитывать, что, в отличие от координатных осей, используемых в планиметрии, на которых значения по оси Y возрастают снизу вверх (ось направлена вверх), на холсте ось Y направлена вниз. Это приводит к тому, что для вычисления на холсте позиции по Y вычисленная для точки координата Y вычитается из начальной координаты Y, а не прибавляется к ней, как в случае со значениями по оси X. — Прим. ред.
После прибавления значения вычисленной координаты по X и вычитания значения по Y. — Прим. ред.
Например, сценарий PyDemos, представленный в предыдущей главе, запускает семь часов, выполняющихся в одном процессе, и во всех них обновление времени на моем (относительно медленном) нетбуке, работающем под управлением Windows 7, происходит плавно. Все вместе они потребляют единицы процентов мощности ЦП и нередко даже меньше, чем сама программа Диспетчер задач (Task Manager).