Programming

Python

Forth Edition

Mark Lutz

O REILLY

Программирование

на Python

том I

Четвертое издание


Марк Лутц

Марк Лутц

Программирование на Python, том I, 4-е издание

Перевод А. Киселева

А. Галунов Н. Макарова П. Щеголев Ю. Бочина С. Минин К. Чубаров

Главный редактор

Зав. редакцией

Выпускающий редактор

Редактор

Корректор

Верстка

Лутц М.

Программирование на Python, том I, 4-е издание. - Пер. с англ. - СПб.: Символ-Плюс, 2011. - 992 с., ил.

ISBN 978-5-93286-210-0

Вы овладели основами Python. Что дальше? Эта книга представляет собой подробное руководство по применению этого языка программирования в основных прикладных областях - системном администрировании, создании графических интерфейсов и веб-приложений. Исследуются приемы работы с базами данных, программирования сетевых взаимодействий, создания интерфейсов для сценариев, обработки текста и многие другие.

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

В четвертое издание включено описание новых особенностей языка, библиотек и практических приемов программирования для Python 3.X. Примеры, представленные в книге, опробованы под третьей альфа-версией Python 3.2.

Можно смело утверждать, что это обстоятельная и всесторонняя книга предназначена быть первой ступенью на пути овладения мастерством разработки приложений на языке Python.

ISBN 978-5-93286-210-0 ISBN 978-0-596-15810-1 (англ)

© Издательство Символ-Плюс, 2011

Authorized translation of the English edition © 2011 O’Reilly Media Inc. This translation is published and sold by permission of O’Reilly Media Inc., the owner of all rights to publish and sell the same.

Все права на данное издание защищены Законодательством РФ, включая право на полное или частичное воспроизведение в любой форме. Все товарные знаки или зарегистрированные товарные знаки, упоминаемые в настоящем издании, являются собственностью соответствующих фирм.

Издательство «Символ-Плюс». 199034, Санкт-Петербург, 16 линия, 7, тел. (812) 380-5007, www.symbol.ru. Лицензия ЛП N 000054 от 25.12.98. Подписано в печать 31.07.2011. Формат 70x100 1/16.

Печать офсетная. Объем 62 печ. л.

Оглавление

Предисловие...........................................................................15

«А теперь нечто совершенно иное...».......................................15

Об этой книге.......................................................................16

О четвертом издании.............................................................18

Влияние Python 3.X на эту книгу............................................26

Использование примеров из книги..........................................31

Как связаться с издательством O’Reilly....................................33

Типографские соглашения.....................................................34

Благодарности........................................................................35

Об авторе...............................................................................38

Часть I. Начало..........................................................................39

Глава 1. Предварительный обзор.............................................41

«Программирование на Python»: краткий очерк.......................41

Постановка задачи................................................................42

Шаг 1: представление записей................................................43

Списки............................................................................43

Словари ..........................................................................48

Шаг 2: сохранение записей на длительное время.......................54

Текстовые файлы.............................................................55

Модуль pickle...................................................................61

Работа модуля pickle с отдельными записями.......................64

Модуль shelve..................................................................66

Шаг 3: переход к ООП............................................................69

Использование классов .....................................................71

Добавляем поведение........................................................73

Добавляем наследование ...................................................74

Реструктуризация программного кода.................................75

Добавляем возможность сохранения...................................79

Другие разновидности баз данных ......................................81

Шаг 4: добавляем интерфейс командной строки........................83

Шаг 5: добавляем графический интерфейс ...............................86

Основы графических интерфейсов......................................87

ООП при разработке графических интерфейсов.....................89

Получение ввода от пользователя.......................................92

Графический интерфейс к хранилищу.................................94

Шаг 6: добавляем веб-интерфейс...........................................102

Основы CGI....................................................................103

Запуск веб-сервера..........................................................106

Использование строки запроса и модуля urllib....................109

Форматирование текста ответа.........................................110

Веб-интерфейс к хранилищу с данными.............................111

Конец демонстрационного примера.......................................123

Часть II. Системное программирование................................127

Глава 2. Системные инструменты..........................................129

«os.path - дорога к знанию» .................................................129

Зачем здесь нужен Python?..............................................129

В следующих пяти главах................................................130

Знакомство с разработкой системных сценариев.....................132

Системные модули Python...............................................133

Источники документации по модулям...............................134

Постраничный вывод строк документации.........................135

Сценарий постраничного вывода.......................................137

Основы использования строковых методов.........................138

Другие особенности строк в Python 3.X:

Юникод и тип bytes........................................................141

Основы операций с файлами ............................................142

Два способа использования программ ...............................143

Руководства по библиотекам Python..................................144

Коммерческие справочники.............................................145

Модуль sys ........................................................................ 146

Платформы и версии ......................................................146

Путь поиска модулей......................................................146

Таблица загруженных модулей........................................148

Сведения об исключениях ...............................................149

Другие элементы, экспортируемые модулем sys .................150

Модуль os..........................................................................150

Инструменты в модуле os.................................................151

Средства администрирования...........................................152

Константы переносимости ............................................... 153

Основные инструменты os.path ........................................153

Выполнение команд оболочки из сценариев ....................... 156

Другие элементы, экспортируемые модулем os .................. 163

Глава 3. Контекст выполнения сценариев...............................167

«Ваши аргументы, пожалуйста!»..........................................167

Текущий рабочий каталог ...................................................168

Текущий рабочий каталог, файлы и путь поиска модулей____168

Текущий рабочий каталог и командные строки ..................170

Аргументы командной строки .............................................. 171

Анализ аргументов командной строки...............................172

Переменные окружения оболочки.........................................175

Получение значений переменных оболочки........................176

Изменение переменных оболочки.....................................177

Особенности переменных оболочки:

родители, putenv и getenv................................................179

Стандартные потоки ввода-вывода........................................180

Перенаправление потоков ввода-вывода

в файлы и программы .....................................................181

Перенаправление потоков

и взаимодействие с пользователем....................................187

Перенаправление потоков в объекты Python.......................192

Вспомогательные классы io.StringIO и io.BytesIO...............196

Перехват потока stderr....................................................197

Возможность перенаправления с помощью функции print____197

Другие варианты перенаправления:

еще раз об os.popen и subprocess........................................198

Глава 4. Инструменты для работы с файлами и каталогами.... 206

«Как очистить свой жесткий диск за пять простых шагов».......206

Инструменты для работы с файлами ..................................... 206

Модель объекта файла в Python 3.X..................................207

Использование встроенных объектов файлов ...................... 209

Двоичные и текстовые файлы........................................... 220

Низкоуровневые инструменты в модуле os

для работы с файлами ..................................................... 233

Сканеры файлов.............................................................239

Инструменты для работы с каталогами .................................. 243

Обход одного каталога.....................................................243

Обход деревьев каталогов ................................................249

Обработка имен файлов в Юникоде

в версии 3.X: listdir, walk, glob.........................................254

Глава 5. Системные инструменты

параллельного выполнения..................................................258

«Расскажите обезьянам, что им делать» ................................258

Ветвление процессов ........................................................... 260

Комбинация fork/exec.....................................................264

Потоки выполнения............................................................270

Модуль _thread..............................................................274

Модуль threading............................................................ 287

Модуль queue.................................................................293

Графические интерфейсы и потоки выполнения:

предварительное знакомство ............................................ 298

Подробнее о глобальной блокировке

интерпретатора (GIL)......................................................302

Завершение программ ......................................................... 306

Завершение программ средствами модуля sys.....................306

Завершение программ средствами модуля os......................307

Коды завершения команд оболочки...................................308

Код завершения процесса

и совместно используемая информация.............................312

Код завершения потока

и совместно используемая информация.............................314

Взаимодействия между процессами.......................................316

Анонимные каналы........................................................318

Именованные каналы (fifo)..............................................331

Сокеты: первый взгляд .................................................... 335

Сигналы ........................................................................ 340

Пакет multiprocessing.........................................................343

Зачем нужен пакет multiprocessing?.................................. 344

Основы: процессы и блокировки.......................................346

Инструменты IPC: каналы, разделяемая память и очереди ... 349

Запуск независимых программ ......................................... 357

И многое другое..............................................................359

Зачем нужен пакет multiprocessing? Заключение ................ 361

Другие способы запуска программ.........................................362

Семейство функций os.spawn...........................................362

Функция os.startfile в Windows........................................366

Переносимый модуль запуска программ ................................368

Другие системные инструменты............................................ 374

Глава 6. Законченные системные программы........................376

«Ярость поиска».................................................................376

Игра: «Найди самый большой файл Python»...........................377

Сканирование каталога стандартной библиотеки................377

Сканирование дерева каталогов стандартной библиотеки.....378

Сканирование пути поиска модулей..................................379

Сканирование всего компьютера....................................... 382

Вывод имен файлов с символами Юникода.........................387

Разрезание и объединение файлов.........................................390

Разрезание файлов переносимым способом......................... 391

Соединение файлов переносимым образом .........................395

Варианты использования................................................. 399

Создание веб-страниц для переадресации ............................... 403

Файл шаблона страницы .................................................404

Сценарий генератора страниц...........................................405

Сценарий регрессивного тестирования ................................... 408

Запускаем тестирование..................................................411

Копирование деревьев каталогов...........................................417

Сравнение деревьев каталогов ..............................................422

Поиск расхождений между каталогами.............................422

Поиск различий между деревьями....................................425

Запускаем сценарий........................................................428

Проверка резервных копий..............................................431

Отчет о различиях и другие идеи ...................................... 433

Поиск в деревьях каталогов..................................................435

grep, glob и find..............................................................436

Создание собственного модуля find...................................437

Удаление файлов с байт-кодом .........................................442

Visitor: обход каталогов «++»...............................................448

Редактирование файлов в деревьях каталогов (Visitor).........454

Глобальная замена в деревьях каталогов (Visitor) ...............456

Подсчет строк исходного программного кода (Visitor)..........458

Копирование деревьев каталогов

с помощью классов (Visitor).............................................460

Другие примеры обходчиков (внешние).............................462

Проигрывание медиафайлов................................................. 464

Модуль webbrowser.........................................................468

Модуль mimetypes..........................................................470

Запускаем сценарий........................................................473

Автоматизированный запуск программ (внешние примеры) ..... 473

Часть III. Программирование графических интерфейсов .... 477

Глава 7. Графические интерфейсы пользователя....................479

«Я здесь, я смотрю на тебя, детка» ........................................479

Темы программирования GUI...........................................479

Запуск примеров ............................................................ 481

Различные возможности создания GUI в Python......................483

Обзор tkinter......................................................................490

Практические преимущества tkinter ................................490

Документация tkinter ..................................................... 492

Расширения для tkinter...................................................492

Структура tkinter...........................................................495

Взбираясь по кривой обучения

программированию графических интерфейсов ........................ 497

«Hello World» в четыре строки (или меньше)......................497

Основы использования tkinter..........................................498

Создание виджетов ......................................................... 499

Менеджеры компоновки .................................................. 500

Запуск программ с графическим интерфейсом....................501

Альтернативные приемы использования tkinter ................. 502

Основы изменения размеров виджетов............................... 504

Настройка параметров графического элемента

и заголовка окна............................................................506

Еще одна версия в память о былых временах......................508

Добавление виджетов без их сохранения ............................ 508

Добавление кнопок и обработчиков.......................................511

Еще раз об изменении размеров виджетов: растягивание......512

Добавление пользовательских обработчиков...........................514

lambda-выражения как обработчики событий.....................515

Отложенные вызовы с применением

инструкций lambda и ссылок на объекты...........................516

Проблемы с областями видимости обработчиков.................518

Связанные методы как обработчики событий......................525

Объекты вызываемых классов как обработчики событий.....527

Другие протоколы обратного вызова в tkinter.....................528

Связывание событий.......................................................529

Добавление нескольких виджетов.........................................530

Еще раз об изменении размеров: обрезание.........................531

Прикрепление виджетов к фреймам..................................532

Порядок компоновки и прикрепление к сторонам ............... 533

Снова о параметрах expand и fill компоновки.....................534

Использование якорей вместо растягивания....................... 536

Настройка виджетов с помощью классов................................537

Стандартизация поведения и внешнего вида.......................538

Повторно используемые компоненты и классы........................ 540

Прикрепление классов компонентов ................................. 542

Расширение классов компонентов..................................... 544

Автономные классы-контейнеры ...................................... 546

Завершение начального обучения ......................................... 549

Соответствие между Python/tkinter и Tcl/Tk..........................551

Глава 8. Экскурсия по tkinter, часть 1......................................553

«Виджеты, гаджеты,

графические интерфейсы... Бог мой!» ....................................553

Темы этой главы.................................................................554

Настройка внешнего вида виджетов......................................554

Окна верхнего уровня..........................................................558

Виджеты Toplevel и Tk....................................................560

Протоколы окна верхнего уровня......................................561

Диалоги ............................................................................ 566

Стандартные (типичные) диалоги.....................................567

Модуль диалогов в старом стиле.......................................580

Пользовательские диалоги............................................... 581

Привязка событий..............................................................585

Другие события, доступные с помощью метода bind.............590

Виджеты Message и Entry....................................................592

Message ......................................................................... 592

Entry ............................................................................ 593

Компоновка элементов ввода в формах..............................595

«Переменные» tkinter и альтернативные способы

компоновки форм...........................................................599

Флажки, переключатели и ползунки ..................................... 602

Флажки ........................................................................ 602

Переключатели..............................................................607

Ползунки......................................................................614

Три способа использования графических интерфейсов.............618

Прикрепление к фреймам................................................619

Независимые окна .......................................................... 624

Запуск программ............................................................626

Изображения.................................................................633

Развлечения с кнопками и картинками ............................. 637

Отображение и обработка изображений с помощью PIL............641

Основы PIL....................................................................641

Отображение других типов графических

изображений с помощью PIL ............................................ 643

Отображение всех изображений в каталоге.........................645

Создание миниатюр изображений

с помощью пакета PIL.....................................................647

Глава 9. Экскурсия по tkinter, часть 2......................................659

«Меню дня: Spam, Spam и еще раз Spam» ...............................659

Меню................................................................................660

Меню окон верхнего уровня ............................................. 660

Меню на основе виджетов Frame и Menubutton...................665

Окна с меню и панелью инструментов................................670

Виджеты Listbox и Scrollbar.................................................676

Программирование виджетов списков ............................... 678

Программирование полос прокрутки................................. 680

Компоновка полос прокрутки...........................................681

Виджет Text.......................................................................683

Программирование виджета Text......................................685

Операции редактирования текста.....................................689

Юникод и виджет Text....................................................695

Более сложные операции с текстом и тегами ......................707

Виджет Canvas...................................................................709

Базовые операции с виджетом Canvas................................710

Программирование виджета Canvas..................................711

Прокрутка холстов.........................................................715

Холсты с поддержкой прокрутки

и миниатюр изображений................................................718

События холстов ............................................................ 722

Сетки................................................................................726

В чем преимущества размещения по сетке? .......................727

Основы работы с сеткой: еще раз о формах ввода.................728

Сравнение методов grid и pack..........................................729

Сочетание grid и pack......................................................731

Реализация возможности растягивания виджетов,

размещаемых по сетке..................................................... 734

Создание крупных таблиц с помощью grid ......................... 738

Инструменты синхронизации,

потоки выполнения и анимация............................................ 747

Использование потоков выполнения

в графических интерфейсах tkinter...................................750

Использование метода after.............................................752

Простые приемы воспроизведения анимации ..................... 755

Другие темы, связанные с анимацией ................................ 762

Конец экскурсии ................................................................ 764

Другие виджеты и их параметры ...................................... 764

Глава 10. Приемы программирования

графических интерфейсов....................................................766

«Создание улучшенной мышеловки».....................................766

GuiMixin: универсальные

подмешиваемые классы ....................................................... 767

Функции создания виджетов............................................ 768

Вспомогательные подмешиваемые классы ......................... 769

GuiMaker: автоматизация создания меню

и панелей инструментов.......................................................773

Протоколы подклассов....................................................778

Классы GuiMaker...........................................................779

Программный код самотестирования GuiMaker..................779

BigGui: клиентская демонстрационная программа .............. 781

ShellGui: графические интерфейсы

к инструментам командной строки........................................785

Обобщенный графический интерфейс

инструментов оболочки...................................................785

Классы наборов утилит....................................................788

Добавление графических интерфейсов

к инструментам командной строки ...................................789

GuiStreams: перенаправление

потоков данных в виджеты................................................... 797

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

сценариев архивирования ...............................................802

Динамическая перезагрузка обработчиков............................. 803

Обертывание интерфейсов окон верхнего уровня.....................805

Графические интерфейсы, потоки выполнения и очереди.........810

Помещение данных в очередь...........................................813

Помещение обработчиков в очередь...................................817

Другие способы добавления GUI

к сценариям командной строки.............................................825

Вывод окон графического интерфейса по требованию..........826

Реализация графического интерфейса в виде отдельной

программы: сокеты (вторая встреча) .................................830

Реализация графического интерфейса в виде

отдельной программы: каналы.........................................835

Запускающие программы PyDemos и PyGadgets......................845

Панель запуска PyDemos.................................................846

Панель запуска PyGadgets...............................................852

Глава 11. Примеры законченных программ

с графическим интерфейсом.................................................857

«Python, открытое программное обеспечение и Camaro»...........857

Примеры в других главах................................................858

Стратегия данной главы..................................................859

PyEdit: программа/объект текстового редактора.....................862

Запуск PyEdit ................................................................ 863

Изменения в версии PyEdit 2.0 (третье издание)..................872

Изменения в версии PyEdit 2.1 (четвертое издание) ............874

Исходный программный код PyEdit..................................888

PyPhoto: программа просмотра и изменения

размеров изображений........................................................917

Запуск PyPhoto..............................................................918

Исходный программный код PyPhoto................................922

PyView: слайд-шоу для изображений и примечаний................929

Запуск PyView...............................................................929

Исходный программный код PyView.................................935

PyDraw: рисование и перемещение графики ........................... 941

Запуск PyDraw ............................................................... 941

Исходный программный код PyDraw.................................943

PyClock: виджет аналоговых/цифровых часов........................951

Краткий урок геометрии..................................................951

Запуск PyClock...............................................................957

Исходный программный код PyClock................................961

PyToe: виджет игры в крестики-нолики.................................969

Запуск PyToe.................................................................969

Исходный программный код PyToe (внешний) ...................971

Что дальше........................................................................974

Алфавитный указатель.........................................................976

Предисловие


«А теперь нечто совершенно иное...»

В этой книге исследуются способы применения языка программирования Python в типичных прикладных областях и в реально возникающих задачах. Эта книга рассказывает, что можно делать с языком Python после того, как вы овладели его основами.

Эта книга предполагает, что читатель еще только начинает знакомиться с рассматриваемыми в книге прикладными областями - графическими интерфейсами, Интернетом, базами данных, системным программированием и так далее, - и представляет каждую из них, начиная с самых азов, выполняя роль учебника. Попутно книга ставит своей целью познакомить читателя с часто используемыми инструментами и библиотеками, но не с основами языка. Таким образом, данная книга является ресурсом, позволяющим читателю получить более глубокое понимание роли языка Python в практике программирования.

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

Это четвертое издание было дополнено представлением новых особенностей языка, библиотек и практических приемов программирования для Python 3.X. В частности, примеры, представленные в книге, выполняются под управлением интерпретатора версии Python 3.1 - наиболее свежей версии Python на момент написания этих строк. Непосредственно перед публикацией книги все основные примеры были опробованы под третьей альфа-версией Python 3.2, но вообще говоря, они должны сохранить свою работоспособность при использовании любой версии Python из линейки 3.X. Кроме того, это издание было реорганизовано с целью упорядочить прежний материал и добавить описание новых инструментов и тем.

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


Об этой книге

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


Экосистема этой книги

Диапазон тем, обсуждаемых в этой книге, позволяет ее рассматривать, как второй том двухтомника, который должен быть дополнен третьим томом. Важно помнить, что эта книга описывает особенности разработки приложений и является продолжением книги «Изучаем Python»1, рассматривающей основы языка, знание которых совершенно необходимо для чтения этой книги. Поясним, как связаны эти книги между собой:

• «Изучаем Python» - подробно описывает основы программирования на языке Python. Основное внимание уделяется базовым особенностям языка Python, знание которых является необходимой предпосылкой для чтения этой книги.

• «Программирование на Python» - эта книга охватывает практические приемы программирования на языке Python. Основное внимание в этой книге уделяется библиотекам и инструментам, и предполагается, что читатель уже знаком с основами языка.

• «Python Pocket Reference» - краткий справочник, в котором охватываются некоторые подробности, отсутствующие в данной книге. Этот справочник не может использоваться в качестве учебника, но он позволит вам быстро отыскивать описание тех или иных особенностей.

В некотором смысле, эта книга является аналогом «Изучаем Python», но в ней раскрываются не основы языка, а основы прикладного программирования. Это последовательный учебник, в котором не делается никаких предположений об уровне вашей подготовки, и каждая тема начинает рассматриваться с самых азов. Например, при изучении темы разработки веб-приложений вы приобретете все необходимые знания, которые позволят вам создавать простые веб-сайты, и получите представление о более развитых фреймворках и инструментах, которые пригодятся вам с ростом ваших потребностей. Обсуждение особенностей конструирования графических интерфейсов также идет по нарастающей - от простого к сложному.

Дополнением к этой книге может служить книга «Python Pocket Reference» (карманный справочник по языку Python), где предоставляется дополнительная информация о некоторых особенностях, не рассматриваемых в данной книге, и которая может служить отличным справочником. Книга «Python Pocket Reference» является всего лишь справочником, и в ней практически отсутствуют примеры и пояснения, но она может служить отличным дополнением к книгам «Изучаем Python» и «Программирование на Python». Поскольку текущее четвертое издание «Python Pocket Reference» содержит информацию об обеих основных версиях Python, 2.X и 3.X, оно также может использоваться читателями, выполняющими переход между этими двумя версиями Python (подробнее об этом чуть ниже)2.


Чего нет в этой книге

Из-за распределения областей рассмотрения по книгам, о которых упоминалось выше, область применения этой книги имеет следующие ограничения:

• Она не раскрывает основы языка Python

• Она не предназначалась для использования в качестве справочника по особенностям языка

Первый из этих двух пунктов отражает тот факт, что освещение основ языка является исключительной прерогативой книги «Изучаем Python», и если вы совершенно не знакомы с языком Python, я рекомендую сначала прочитать книгу «Изучаем Python», прежде чем приниматься за эту книгу, так как здесь предполагается знание основ языка.

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

Второй из этих двух пунктов отражает тот факт, что за многие годы об этой книге сложились неверные представления (вероятно, стоило назвать эту книгу «Применение Python», будь мы чуть более прозорливы в далеком 1995 году). Я хочу ясно обозначить: эта книга - не справочник. Это учебник. Здесь вы можете найти некоторые подробности, воспользовавшись оглавлением или алфавитным указателем, но данная книга не предназначалась для использования именно в таких целях. Краткий справочник вы найдете в книге под названием «Python Pocket Reference», который вы найдете весьма полезным, как только начнете самостоятельно писать нетривиальный программный код. Существуют и другие источники справочной информации, в том числе другие книги и собственный набор справочных руководств по языку Python. Цель этой книги - постепенное обучение применению языка Python для решения типичных задач, а не подробное описание мельчайших особенностей.


О четвертом издании

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

• Оно охватывает только Python 3.X.

• Оно было сокращено, чтобы сделать книгу еще направленнее и освободить место для новых тем.

• В него было добавлено обсуждение новых тем и инструментов, появившихся в мире Python.

Первый из этих пунктов является, пожалуй, наиболее важным - это издание опирается на Python 3.X, на стандартную библиотеку для этой версии и на распространенные приемы программирования, используемые его пользователями. Однако чтобы объяснить, как это и два других изменения отразились на данном издании, я должен поведать о некоторых деталях.


Изменения в этом издании

Предыдущие версии книги получили весьма широкое распространение, поэтому ниже я приведу некоторые из наиболее заметных изменений в этом издании:

Существовавший ранее материал был сжат, чтобы освободить место для новых тем

Предыдущее издание книги также имело объем около 1600 страниц, что не позволило выделить достаточно места для рассмотрения новых тем (одна только ориентированность Python 3.X на использование Юникода предполагает массу нового материала). К счастью, недавние изменения в мире Python позволили нам без особого ущерба выкинуть часть существующего материала и освободить место для новых тем.

Глубина обсуждения оставшихся тем при этом не пострадала - эта книга остается такой же основательной, как и прежде. Тем не менее одной из основных задач, стоявших при подготовке этого издания, было не допустить дальнейшего роста его объема, а множество других изменений и сокращений, о которых я упомяну ниже, были сделаны отчасти для того, чтобы включить новые темы.

Рассматривается только Python 3.X

Примеры и пояснения были изменены с учетом того, что теперь эта книга охватывает только версию Python 3.X. Версия Python 2.X больше не поддерживается, за исключением тех особенностей, которые перекочевали из версии 2.X в версию 3.X без изменений. Несмотря на то, что таких особенностей достаточно много, благодаря чему читатели могут использовать версию 2.X, тем не менее формально книга поддерживает только версию 3.X.

В свою очередь это обстоятельство явилось основным фактором, обеспечившим сохранение объема этого издания на прежнем уровне. Ограничившись поддержкой только версии Python 3.X - несовместимой с версией Python 2.X, которую следует рассматривать как будущее языка Python, - нам удалось избежать дублирования описания особенностей, отличающихся в этих двух версиях Python. Такое ограничение поддерживаемых версий особенно важно для такой книги, как эта, где приводится множество расширенных примеров, так как это позволяет демонстрировать примеры только для одной версии.

Для тех, кто по-прежнему пытается удержаться в обоих мирах,

2.X и 3.X, я подробнее расскажу об изменениях в Python 3.X ниже, в этом же предисловии. Самым важным, пожалуй, изменением в версии 3.X, из тех, что описываются в книге, является усовершенствованная поддержка интернационализации в примерах программ PyEdit и PyMailGUI. Несмотря на то, что в версии 2.X также имеется поддержка Юникода, тем не менее усовершенствованная ее реализация в версии 3.X вынуждает заново пересмотреть реализацию подобных систем, прежде ориентированных на работу с кодировкой ASCII.

Включение недавно появившихся библиотек и инструментов

С момента выхода предыдущего издания появилось или получило дальнейшее развитие множество новых библиотек и инструментов, и они также упоминаются здесь. В их число входят новые инструменты стандартной библиотеки языка Python, такие как модули subprocess (рассматривается в главах 2 и 3) и multiprocessing (рассматривается в главе 5), а также новые веб-фреймворки, созданные сторонними разработчиками, и инструменты ORM (Object-Relational Mapping - объектно-реляционное отображение) для работы с базами данных. Большинство из них рассматриваются не очень подробно (многие популярные расширения сами по себе являются сложными системами и гораздо подробнее описаны в соответствующей литературе), но для них дается по крайней мере краткое описание в виде резюме.

Например, новая библиотека виджетов Tk tkinter.ttk рассматривается в главе 7, но весьма кратко. Как правило, в этом издании мы предпочитали упоминать подобные расширения по ходу дела, вместо того чтобы представлять примеры программного кода без внятного пояснения.

Это предисловие было ужато

Я удалил все инструкции по запуску и использованию примеров программ. Поэтому теперь за инструкциями по использованию обращайтесь к файлам README, входящим в состав дистрибутива с комплектом примеров. Кроме того, я убрал большую часть благодарностей, потому что они повторяют благодарности из книги «Изучаем Python», - так как знакомство с книгой «Изучаем Python» теперь считается необходимой предпосылкой, дублирование одного и того же материала здесь ничем не оправдано. Кроме того, было убрано описание содержимого книги - чтобы ознакомиться со структурой книги, обращайтесь к оглавлению.

Была убрана вводная глава с обзором языка Python

Я удалил «организаторскую» главу, присутствовавшую в предыдущем издании, где описывались сильные стороны языка Python, представлялись наиболее видные пользователи, рассматривались различные философии и так далее. Обращение в свою веру играет важную роль в любой сфере, где вопрос «почему» задается менее часто, чем должен бы. В действительности, если бы мастера Python не занимались его популяризацией, все мы, вероятно, использовали бы сейчас Perl или языки командных оболочек!

Однако присутствие здесь такой главы стало совершенно излишним из-за наличия сходной главы в книге «Изучаем Python». Поскольку книга «Изучаем Python» должна предшествовать этой книге, я решил не расходовать книжное пространство на повторную агитацию «Питонистов» («Pythonista»). В этой книге предполагается, что вы уже знаете, почему стоит использовать Python, поэтому мы сразу же перейдем к его применению.

Было убрано заключительное послесловие

Заключительное послесловие к этой книге было написано еще для первого издания, и теперь ему исполнилось уже 15 лет. Естественно, что оно отражает взгляды на Python, в большей степени характерные для того времени. Например, использование языка Python для разработки гибридных приложений казалось более значимым в 1995 году, чем в 2010. В современном, более обширном мире Python большинству пользователей не приходится иметь дело со связанным программным кодом на языке C.

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

Было убрано вступительное слово

По похожим причинам, представленным в двух предыдущих пунктах, я убрал разделы со вступительным словом к предыдущим изданиям. Те, кому это будет интересно, историческую справку о вкладе Гвидо ван Россума (Guido van Rossum), создателя Python, в развитие языка смогут найти в Интернете. Если вам интересно, как за эти годы изменился язык Python с технической точки зрения, смотрите документ «What’s New» («Что нового»), входящий в состав стандартного комплекта руководств по языку Python (доступен по адресу http://www.python.org/doc и устанавливается вместе с Python в Windows и на других платформах).

Раздел, посвященный интеграции с языком C, был сокращен до одной

главы

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

Часть, посвященная системному программированию, была сокращена

и переработана

Прежние две главы с большими примерами использования Python в системном программировании были объединены в одну, более короткую главу с новыми или значительно переработанными примерами. Фактически эта часть (часть II) подверглась самым значительным изменениям. Она включает описание новых инструментов, таких как модули subprocess и multiprocessing, знакомит читателей с сокетами, а кроме того, из нее были удалены устаревшие сведения и примеры, унаследованные из прежних изданий. Честно признаться, несколько примеров работы с файлами были созданы еще в 1990-х годах и оказались сильно устаревшими. Начальная глава в этой части была разбита на две, чтобы упростить чтение материала (описание контекста командной оболочки, включая потоки ввода-вывода, было вынесено в отдельную главу), а несколько листингов крупных программ (включая запускающие сценарии с автоматической настройкой) теперь вынесены за пределы книги и включены в состав дистрибутива с комплектом примеров.

Некоторые крупные примеры были исключены из книги (но остались

в составе дистрибутива с комплектом примеров)

Точно так же из книги были исключены два крупных примера, демонстрирующих создание графического интерфейса, PyTree и PyForm. Однако их обновленная реализация доступна в комплекте примеров. В этом издании вы все еще сможете найти упоминание и описание множества крупных примеров, включая примеры реализации полноценных клиентов электронной почты с графическим и веб-интерфейсом, а также программы для просмотра изображений, калькуляторы, часы, текстовые редакторы с поддержкой Юникода, простые графические редакторы, сценарии регрессивного тестирования и многие другие. Однако, так как программный код примеров не добавляет ничего важного к раскрытию темы и вообще эти примеры предлагались в основном для самостоятельного изучения, - я перевел их в разряд дополнительной информации и исключил их из текста этого издания книги.

Обширная глава с описанием тем, касающихся Интернета, была заменена кратким обзором

Я полностью убрал обширную главу с описанием тем, касающихся Интернета, оставив лишь краткий обзор в начале части (с акцентом на возможностях создания графического интерфейса, который приводится в начале третьей части «Программирование GUI»). Здесь вы найдете все ранее включавшиеся в рассмотрение инструменты, такие как веб-фреймворк ZOPE, объектная модель COM, технологии Windows Active Scripting и ASP, HTMLgen, Python Server Pages (PSP), Jython и уже серьезно устаревшая система Grail. Некоторые из этих инструментов по-прежнему заслуживают положительных оценок, но в этом издании никакие из них не рассматриваются подробно. В обзор были добавлены новые инструменты (включая многие из тех, что перечислены в следующем абзаце), но, опять же, весьма краткие и без примеров программного кода.

Несмотря на все попытки автора угадать направления развития вебтехнологий в будущем, печатное издание не способно полностью соответствовать эволюции сферы развития Интернета. Например, в настоящее время появились веб-фреймворки, такие как Django, Google App Engine, TurboGears, pylons и web2py, соперничающие по своей популярности с ZOPE. Точно так же фреймворк .NET Framework во многих приложениях вытеснил объектную модель Windows COM. Реализация IronPython теперь способна обеспечить такую же тесную интеграцию с .NET, как и Jython с Java. А механизм Active Scripting в значительной степени может быть замещен клиентскими фреймворками, основанными на JavaScript и использующими технологию AJAX, такими как Flex, Silverlight и pyjamas (которые часто называют средствами разработки полнофункциональных вебприложений). Кроме собственно исторической ценности, примеры, ранее представленные в этой категории, не давали возможности изучить описываемые инструменты или хотя бы судить об их достоинствах.

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

Единственное исключение: описание XML, присутствовавшее ранее в этой главе, было дополнено и перемещено в главу, посвященную обработке текста (где оно и должно было бы находиться). Точно так же было сохранено описание объектно-ориентированной базы данных ZODB, поддерживаемой фреймворком ZOPE, хотя и в сильно урезанном виде, чтобы получить возможность добавить описание механизмов ORM, таких как SQLObject и SQLAlchemy (также в краткой форме).

Задействованы, современные инструменты, доступные в версии 3.X

К моменту написания этих строк Python 3.X все еще находился на этапе внедрения, и некоторые из инструментов сторонних разработчиков, которые использовались в примерах в предыдущих изданиях этой книги, по-прежнему доступны только в версиях для Python 2.X. Чтобы обойти этот временный недостаток, я изменил некоторые примеры, задействовав в них альтернативные инструменты, обеспечивающие поддержку версии Python 3.X.

Наиболее заметным в этом смысле является раздел, посвященный базам данных SQL, - теперь в нем вместо интерфейса доступа к серверу MySQL, присутствующего в Python 2.X, используется библиотека SQLite поддержки баз данных, встраиваемых в приложения, которая в версии 3.X стала стандартной частью Python. К счастью, переносимый прикладной интерфейс Python позволяет сценариям взаимодействовать с обоими механизмами практически одинаково, поэтому такое изменение является весьма незначительной жертвой.

Отдельно следует отметить использование расширения PIL для отображения изображений в формате JPEG в части, посвященной созданию графического интерфейса. Это расширение было адаптировано Фредриком Лундом (Fredrik Lundh) для версии Python 3.1 как раз к моменту подготовки этого издания. Когда я сдавал в издательство окончательный вариант рукописи этой книги в июле 2010 года, эта версия расширения официально еще не была выпущена, но она должна была вскоре выйти; поэтому в качестве временной меры заплаты для этой библиотеки, обеспечивающие поддержку Python 3.X, были включены в комплект примеров.

Было исключено описание дополнительных возможностей языка

Все дополнительные особенности языка Python, такие как дескрипторы, свойства, декораторы, метаклассы и поддержка Юникода, являются частью языка Python. Поэтому их описание было перемещено в четвертое издание книги «Изучаем Python». Например, улучшенная поддержка Юникода и ее влияние на приемы работы с файлами, именами файлов, сокетами и со многими другими инструментами обсуждаются в этой книге, но основы Юникода здесь не рассматриваются. Некоторые темы из этой категории определенно имеют прикладной характер (или, по крайней мере, представляют интерес для разработчиков инструментальных средств и архитекторов прикладных интерфейсов), но наличие их описания в книге «Изучаем Python» позволило избежать дальнейшего увеличения объема этой книги. Ищите подробное обсуждение этих тем в книге «Изучаем Python».

Прочие незначительные изменения

Естественно, что попутно было внесено множество мелких изменений. Например, для размещения элементов форм теперь вместо метода pack используется метод grid из библиотеки tkinter, потому что он обеспечивает более непротиворечивый способ размещения элементов в платформах, где размер шрифта в подписях не соответствует высоте полей ввода (включая ОС Windows 7 netbook, установленную на ноутбуке, использовавшемся для работы над этим изда-

нием). Кроме того, по всей книге были добавлены новые сведения, включая новое описание механизма переадресации потоков ввода-вывода в сокеты, в части с описанием приемов работы в Интернете; новый многопоточный диалог поиска по регулярным выражениям с поддержкой Юникода и изменения в тестах для примера PyEdit; множество других изменений, которые, вероятно, вам будет лучше раскрывать по ходу дела, чем читать о них в предисловии.

Наконец, некоторые блоки комментариев, начинающиеся с символа «#» и расположенные в начале файлов с исходными текстами, я заменил строками документирования (и, для единообразия, даже в сценариях, которые не предназначены для импортирования, хотя отдельные строки «#» остались в крупных примерах, где они отделяют текст). Я также заменил несколько устаревших операторов «while 1» на «while True»; чаще стал использовать оператор +=; внес другие изменения, исправив некоторые устаревшие шаблоны программирования. Старые привычки бывает сложно искоренять, но подобные изменения делают примеры не только более функциональными, но и более полно отражающими современные приемы программирования.

Несмотря на добавление новых тем, в общей сложности было удалено четыре главы (нетехническое введение, одна из глав с примерами по системному программированию, глава с расширенными темами, касающимися Интернета, и одна объединительная глава). Были урезаны несколько дополнительных примеров и сопутствующий им материал (включая PyForm и PyTree), а также, специально для экономии пространства, книга ограничивается представлением только версии Python 3.X и описанием лишь самых основ разработки приложений.


Что же осталось?

В результате изменений, обозначенных выше, это издание получилось более кратким и более четко отражающим основную его роль - учебное руководство по применению языка Python для решения типичных задач программирования. Однако, учитывая объем книги, можно смело утверждать, что это по-прежнему обстоятельная и всесторонняя книга, предназначенная быть первой ступенью на пути овладения мастерством разработки приложений на языке Python.

Вопреки последним настроениям (и рискуя получить клеймо еретика) я совершенно уверен, что книги, подобные этой, должны подтягивать своих читателей вверх, а не опускаться до их уровня. Снижение интеллектуальной планки вредит не только читателям, но и той области знаний, в которой они предполагают действовать. В этой книге вы не найдете множество забавных рисунков, как в некоторых, и она не будет поражать вас развлекательным повествованием вместо технической глубины. Цель моих книг состоит в том, чтобы передать сложные поня-

тия убедительным и надежным способом и снабдить вас инструментами, которые потребуются вам в разработке программного обеспечения.

Разумеется, существует множество типов обучающихся, и ни одна книга не сможет работать на любую аудиторию. Фактически именно по этой причине изначальная версия этой книги позднее была разделена на две, и описание основ языка было делегировано отдельной книге «Изучаем Python». Кроме того, и программистов можно поделить на две категории - тех, кто желает получить глубокие знания в области разработки программного обеспечения, и скриптеров, не испытывающих такой потребности. Некоторым вполне достаточно иметь элементарные знания, позволяющие дорабатывать системы или библиотеки и решать текущие проблемы. Но это пока они не начнут вторгаться в область разработки полномасштабных приложений - порог, за которым в худшем случае может наступить разочарование, а в лучшем - лучшее понимание сложной природы этой области.

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

В конечном счете, овладеть навыками программирования далеко не так просто, как пытаются представить некоторые. Однако если вы приложите необходимые усилия, то обнаружите, что это стоит затраченного времени. Это особенно верно для тех, кто вооружает себя удобным инструментом программирования, таким как язык Python. Ни одна книга и ни одни курсы не превратят вас в «Повелителя Вселенной» Python, тем не менее цель этой книги состоит в том, чтобы помочь вам добиться этого, сократив начальный этап освоения и обеспечив надежный фундамент в наиболее типичных областях применения Python.


Влияние Python 3.X на эту книгу

Как уже упоминалось выше, это издание теперь охватывает только версию Python 3.X. Версия языка Python 3.X несовместима с версией 2.X. В своей основе язык версии 3.X очень напоминает Python 2.X, но имеет множество существенных отличий, кроющихся как в самом языке, так и в стандартной библиотеке. Читатели, не имеющие опыта работы с версией 2.X, могут пропустить описание этих отличий, но появившиеся изменения очень сильно повлияли на содержание этого издания. Для широкого круга пользователей Python 2.X в этом разделе описываются наиболее значимые изменения, относящиеся к этой категории.

Если вам интересно поближе познакомиться с отличиями от версии 2.X, я предлагаю дополнительно найти четвертое издание книги «Python Pocket Reference», упомянутое выше. Там приводятся описания основных структур языка обеих версий, 2.X и 3.X, встроенных функций и исключений, а также перечисляется большинство модулей из стандартной библиотеки и инструментов, используемых в этой книге. Хотя четвертое издание книги «Изучаем Python» не является справочником по различиям между версиями, оно охватывает обе версии,

2.X и 3.X, и, как уже отмечалось, знакомство с ней является обязательным условием для усвоения материала этой книги. Цель этого издания книги «Программирование на Python», ориентированного только на версию 3.X, заключается вовсе не в том, чтобы оставить за бортом огромное количество пользователей версии 2.X, а в том, чтобы помочь читателям перейти на новую версию и избежать увеличения размеров и без того массивной книги.


Изменения, связанные с включением поддержки версии 3.X

К счастью, многие отличия между версиями 2.X и 3.X, обусловившие необходимость внесения изменений в эту книгу, достаточно тривиальны. Например, библиотека tkinter, широко используемая в этой книге для построения графических интерфейсов, присутствует в версии 3.X под именем tkinter и имеет структуру пакета - ее прежняя инкарнация в версии 2.X, в виде модуля Tkinter, в этой книге не описывается. Это отличие приводит, в основном, к необходимости использовать отличные инструкции импортирования, но здесь приводятся только инструкции для версии Python 3. Аналогично с целью соблюдения соглашений об именовании модулей, принятых в версии 3.X, модули для версии 2.X anydbm, Queue, thread, StringIO.StringIO и urllib.open превратились в Python 3.X и в этом издании в модули dbm, queue, _thread, io. StringIO и urllib. request.urlopen соответственно. Точно так же были переименованы и другие инструменты.

С другой стороны, переход к версии 3.X предполагает более широкие идиоматические изменения, которые, конечно же, являются более радикальными. Например, усовершенствованная поддержка Юникода в Python 3.X подтолкнула к созданию для этого издания примеров полностью интернационализированных версий текстового редактора PyEdit и клиента электронной почты PyMailGUI (подробнее об этом чуть ниже). Кроме того, замена модуля os.popen2 модулем subprocess потребовала включения новых примеров; отказ от модуля os.path.walk в пользу модуля os.walk позволил сократить некоторые примеры; новое разделение на файлы и строки Юникода и двоичные файлы и строки потребовало изменения группы дополнительных примеров и описания; кроме того, появились новые модули, такие как multiprocessing, предлагающие новые возможности, которые необходимо было описать в этом издании.

Помимо изменений в библиотеке, в примерах этого издания также отражены изменения в языке Python 3. Например, здесь учтены все изменения, коснувшиеся функций из версии 2.X print, raw_input, keys, has_key, map и apply. Кроме того, новая модель импортирования относительно пакетов, появившаяся в версии 3.X, нашла отражение в некоторых примерах, таких как mailtools и анализаторы выражений, а отличия в поведении операторов деления вынудили внести небольшие изменения в примеры создания графического интерфейса, такие как PyClock, PyDraw и PyPhoto.

Замечу также, что я не стал заменять все выражения форматирования строк на основе оператора % новым методом str.format, потому что оба способа форматирования поддерживаются в Python 3.1, и похоже, оба они будут поддерживаться еще очень долго, если не всегда. Фактически если воспользоваться поиском с помощью регулярных выражений, который мы реализуем в примере текстового редактора PyEdit в главе 11, можно обнаружить, что этот оператор встречается более 3000 раз в программном коде библиотеки для Python 3.1. Я не могу с абсолютной точностью предсказать, как будет развиваться Python в будущем, поэтому обращайтесь к первой главе, где подробнее рассказывается об этом, если когда-нибудь вам потребуется внести изменения.

Кроме того, из-за того, что это издание охватывает только версию 3.X, оказалось невозможным использовать некоторые сторонние пакеты, существующие только в версии для Python 2.X, о чем уже говорилось выше. В их число входят интерфейс к MySQL, ZODB, PyCrypto и другие. Как уже упоминалось выше, для работы под управлением Python 3.1 была адаптирована библиотека PIL с целью использования в этой книге, но для этого потребовалось наложить специальные исправления, а официальная версия, поддерживающая Python 3.X, до сих пор не вышла. Многие из недостающих модулей для версии 3.X могут появиться к моменту, когда вы будете читать эти строки, либо в виде адаптированных версий для Python 2.X, либо в виде совершенно новых версий, специально для Python 3.X.


Особенности языка и библиотека: Юникод

Поскольку эта книга посвящена изучению принципов разработки приложений, а не основ языка программирования, изменения в языке не обязательно должны отслеживаться здесь. В действительности, оглядываясь на книгу «Изучаем Python», можно сказать, что изменения в языке, связанные с переходом на версию 3.X скорее касаются ее, а не данной книги. В большинстве случаев изменения в примерах к этой книге были обусловлены необходимостью сделать их более понятными или более функциональными, а не включением поддержки версии 3.X.

С другой стороны, переход на версию Python 3.X оказывает влияние на значительную часть программного кода, и иногда это влияние может оказаться весьма тонким. Тем не менее читатели с опытом использования Python 2.X обнаружат, что если отличия в версии 3.X языка чаще всего легко преодолимы, то отличия в стандартной библиотеке для версии 3.X преодолеть иногда оказывается гораздо сложнее.

Но к наиболее широким последствиям привело главное изменение в Python 3.X - улучшенная поддержка строк Юникода. Будем честными: поддержка Юникода в версии 3.X иногда может существенно осложнять жизнь тех, кто всю жизнь сталкивался только с кодировкой ASCII! Как мы увидим далее в этой книге, эта поддержка оказывает существенное влияние при работе с содержимым файлов, с именами файлов, с дескрипторами каналов, с сокетами, при выводе текста в графическом интерфейсе, при работе с такими протоколами Интернета, как FTP и email, при разработке сценариев CGI и даже при использовании некоторых инструментов хранения данных. Плохо это или хорошо, но как только мы войдем в мир разработки приложений, описываемый в этой книге, Юникод перестанет быть необязательной темой для многих, если не для большинства программистов на языке Python 3.X.

Конечно, если уж на то пошло, никому и никогда не следовало бы рассматривать использование Юникода, как дополнительную и необязательную возможность. Далее мы увидим, что некоторые приемы, которые, казалось бы, работают в Python 2.X, на самом деле нельзя признать удовлетворительными - работа с текстом как с простым набором байтов может порождать различные проблемы, такие как ошибки при сравнении строк в различных кодировках (утилита grep, реализованная в составе текстового редактора PyEdit в главе 11, является ярким примером программного кода, который должен терпеть неудачу при отказе от использования Юникода). Python 3.X обнажает подобные проблемы, делая их более заметными для программиста.

Однако перенос нетривиального программного кода на версию 3.X не является неразрешимой задачей. Кроме того, многие читатели этого издания имеют шикарную возможность начать использовать язык Python сразу же с версии 3.X и не иметь дела с существующим программным кодом для версии 2.X. Если вы принадлежите к их числу, вы увидите, что Python 3.X является надежным языком широкого применения для разработки сценариев и приложений, стремящимся устранить многие проблемы, которые когда-то скрывались в версии 2.X.


Ограничения Python 3.1: электронная почта, CGI

Здесь необходимо сделать одно важное замечание, касающееся основных примеров в книге. Чтобы их реализация представляла интерес для как можно более широкой аудитории, основные примеры в этой книге имеют отношение к электронной почте и обеспечивают поддержку интернационализации и Юникода. К этой категории относятся примеры PyMailGUI (в главе 14) и PyMailCGI (в главе 16), а также все предшествующие примеры, используемые этими приложениями, в число которых входит текстовый редактор PyEdit, поддерживающий Юникод при работе с файлами, при отображении и поиске текста.

В этом есть свои плюсы и минусы. Плюс в том, что в конечном итоге мы получим полнофункциональный и интернационализированный клиент электронной почты PyMailGUI, использующий существующий ныне пакет email. Это приложение будет поддерживать любые кодировки для содержимого и заголовков электронных писем и обеспечит возможность не только их просмотра, но и составления. Минус заключается в том, что при этом придется приложить определенные усилия, чтобы обойти сложности, связанные с особенностями реализации пакета email в Python 3.1.

К сожалению, как будет показано в главе 13, в пакете email в Python 3.1 имеется ряд проблем, связанных с обработкой типов str/bytes в Python 3.X. Например, отсутствует простой способ определить кодировку для преобразования текста письма, возвращаемого модулем poplib в виде объекта типа bytes, в тип str, который ожидает получить парсер email. Кроме того, в настоящее время пакет email не в состоянии обрабатывать некоторые виды сообщений, а поддержка некоторых типов сообщений реализована неправильно или слишком специфично.

Эта ситуация носит, скорее всего, временный характер. Исправление некоторых из проблем, с которыми нам придется столкнуться в этой книге, уже запланировано разработчиками. (Фактически из-за одного из таких исправлений, выполненных в версии 3.2, в последний момент потребовалось внести изменения в один из примеров в главе 13.) Кроме того, ведется разработка новой версии пакета email, в которой будут учтены все особенности поддержки Юникода и типа bytes в версии 3.X, но новая версия пакета будет выпущена значительно позже выхода этой книги, и она может оказаться несовместимой с API текущей версии пакета, как и сам Python 3.X. По этой причине в книге приводятся не только обходные решения, но и попутно делаются некоторые предположения. Настоятельно рекомендую регулярно посещать веб-сайт книги (описывается ниже), где будут приводиться сведения об изменениях в будущих версиях Python. Один из плюсов этой ситуации состоит в том, что детальное описание проблемы отражает существующие реалии разработки приложений - основной темы этой книги.

Проблемы, наблюдающиеся в пакете email, также в значительной степени были унаследованы реализацией модуля cgi в версии 3.1. Сценарии CGI - это одна из простейших технологий, на смену которой приходят веб-фреймворки, тем не менее они по-прежнему могут служить целям обучения основам Веб и все еще составляют основу множества крупных наборов инструментальных средств. Скорее всего, эти недостатки версии 3.1 также будут исправлены в будущем, но нам придется приложить определенные усилия, чтобы реализовать в сценариях CGI выгрузку текстовых файлов в главах 15 и 16 и вложений в сообщениях электронной почты в приложении PyMailCGI. Казалось бы, спустя два года после выхода версии Python 3.0 такое положение дел как минимум недопустимо, но такова жизнь в динамическом мире разработки программного обеспечения и в мире книг, которые стремятся вести за собой, а не плестись в хвосте.


Использование примеров из книги

Поскольку примеры составляют основную часть содержимого этой книги, я должен сказать несколько слов о них.


Где искать примеры и обновления

Как и прежде, примеры, обновления, исправления и дополнения к этой книге можно найти на веб-сайте автора, по адресу:

http://www.rmi.net/~lutz/about-pp4e.html

На этой странице веб-сайта моей книги будут даваться ссылки на дополнительную информацию, имеющую отношение к данной версии книги. Однако я не являюсь владельцем этого доменного имени, поэтому если указанная ссылка перестанет работать на протяжении срока жизни этого издания, попробуйте обратиться на другой сайт, по адресу:

http://learning-python.com/books/about-pp4e.html (альтернативная страница)

Если перестанут действовать обе ссылки, попробуйте выполнить поиск в Интернете (не сомневаюсь, что большинство читателей предпримут именно этот шаг).

На веб-сайте книги (а также на сайте издательства O’Reilly, о котором говорится в следующем разделе), где бы он ни находился, вы сможете загрузить дистрибутив с комплектом примеров - файл архива, содержащий все примеры, которые приводятся в книге, а также несколько дополнительных примеров, которые упоминаются, но отсутствуют в самой книге. Чтобы иметь возможность опробовать примеры и избавить себя от необходимости вводить их вручную, загрузите архив, распакуйте его и ознакомьтесь с содержимым файла README.txt, где приводятся инструкции по использованию. Порядок именования файлов примеров и структуру дерева каталогов пакета я опишу ниже, когда мы перейдем к опробованию первого сценария в первой главе.

Как и в случае с первыми тремя изданиями, я буду поддерживать на этом веб-сайте неофициальный «блог», где будут описываться изменения в языке Python, а также будут даваться пояснения и обновления в книге, который вы можете рассматривать, как дополнительное приложение.

Кроме того, на веб-сайте издательства O’Reilly, о котором говорится ниже, имеется система регистрации сообщений об опечатках, где вы сможете сообщить об обнаруженных ошибках. Аналогичная страница присутствует на моем сайте книги. Я стараюсь обновлять веб-сайты моих книг как можно чаще, тем не менее может так получиться, что страница на сайте издательства O’Reilly со списком опечаток будет содержать более свежую информацию. В любом случае в качестве официального источника информации об ошибках и исправлениях следует рассматривать объединение этих двух списков.


Переносимость примеров

Примеры для этой книги разрабатывались, тестировались и запускались под управлением ОС Windows 7 и Python 3.1. Непосредственно перед передачей книги в печать все основные примеры успешно прошли тестирование под управлением грядущей версии Python 3.2 (третья альфа-версия), то есть все, о чем рассказывается в этой книге, в равной степени относится и к Python 3.2. Кроме того, программный код на языке C из главы 20 и ряд примеров параллельного программирования были опробованы в Windows под управлением оболочки Cygwin, имитирующей окружение Unix.

Несмотря на то, что Python и стандартная библиотека, вообще говоря, нейтральны в отношении используемой платформы, тем не менее в некоторые примеры необходимо будет внести незначительные изменения, чтобы их можно было опробовать на других платформах, таких как Mac OS X, Linux и в других разновидностях ОС Unix. Примеры с графическим интерфейсом на основе пакета tkinter, а также некоторые примеры из раздела, посвященного системному программированию, могут быть особенно чувствительны к различиям между платформами. Часть проблем, связанных с переносимостью, будут отмечаться в ходе обсуждения примеров, но некоторые проблемы могут не упоминаться явно.

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


Сценарии запуска демонстрационных программ

В состав пакета с примерами, который был описан выше, также входят сценарии PyDemos и PyGadgets запуска демонстрационных программ. Они позволяют быстро ознакомиться с некоторыми основными примерами с графическим и веб-интерфейсом. Запускающие их сценарии, находящиеся на верхнем уровне дерева каталогов пакета с примерами, предназначены для настройки пути поиска модулей в запускаемых ими программах и могут использоваться непосредственно на совместимых платформах, включая Windows. Более подробную информацию об этих сценариях вы найдете в файлах README, а также в кратких обзорах, которые приводятся в конце главы 6 и 10.


Политика повторного использования программного кода

Мы прерываем предисловие, чтобы вставить несколько слов от имени юридического отдела. Данная книга призвана оказать вам помощь в решении ваших задач. Вообще вы можете свободно использовать примеры программного кода из этой книги в своих приложениях и в документации. Вам не нужно обращаться в издательство за разрешением, если вы не собираетесь воспроизводить существенные части программного кода. Например, если вы разрабатываете программу и используете в ней несколько отрывков программного кода из книги, вам не нужно обращаться за разрешением. Однако в случае продажи или распространения компакт-дисков с примерами из этой книги вам необходимо получить разрешение от издательства O’Reilly. Для цитирования данной книги или примеров из нее, при ответе на вопросы не требуется получение разрешения. При включении существенных объемов программного кода примеров из этой книги в вашу документацию вам необходимо будет получить разрешение издательства.

Мы приветствуем, но не требуем добавлять ссылку на первоисточник при цитировании. Под ссылкой на первоисточник мы подразумеваем указание названия книги, авторов, издательства и ISBN. Например: «Programming Python, Fourth Edition, by Mark Lutz (O’Reilly). Copyright 2011 Mark Lutz, 978-0-596-15810-1».


Как связаться с издательством O'Reilly

В предыдущем разделе я описал свои собственные сайты, где можно найти примеры и обновления. В дополнение к тем сайтам вы можете обратиться на сайт издательства с вопросами и предложениями, касающимися этой книги:

O’Reilly Media

1005 Gravenstein Highway North

Sebastopol, CA 95472

800-998-9938 (в Соединенных Штатах Америки или в Канаде)

707-829-0515 (международный)

707-829-0104 (факс)

Как уже говорилось выше, на сайте издательства O’Reilly поддерживается веб-страница для этой книги, где можно найти список опечаток, файлы с примерами и другую дополнительную информацию:

http://www.oreilly.com/catalog/9780596158101

Свои пожелания и вопросы технического характера отправляйте по адресу:

bookquestions@oreilly.com

Дополнительную информацию о книгах, обсуждения, программное обеспечение, Центр ресурсов издательства O’Reilly вы найдете на сайте:

http://www.oreilly.com


Типографские соглашения

В этой книге приняты следующие соглашения:

Курсив

Курсив применяется для выделения имен файлов и каталогов, новых терминов и некоторых комментариев в примерах программного кода.

Моноширинный шрифт

Применяется для представления листингов программ, а также для выделения в обычном тексте программных элементов, таких как имена модулей, методов, параметров, классов, функций, инструкций, программ, объектов и тегов HTML.

Моноширинный жирный

Используется для выделения команд или текста, который должен быть введен пользователем.

Моноширинный курсив

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

Так выделяются примечания, имеющие отношение к текущему обсуждению.

Так выделяются предупреждения или предостережения, имеющие отношение к текущему обсуждению.

Благодарности

Я благодарен всем, кто перечислен в предисловии к четвертому изданию книги «Изучаем Python», вышедшему меньше года тому назад. Так как знакомство с книгой «Изучаем Python» является обязательным условием для чтения этой книги, а также потому что люди, помогавшие мне в создании обеих книг, - одни и те же, я не стал повторять весь список здесь. Но, как бы то ни было, я хотел бы выразить благодарность:

• Издательству O’Reilly за продвижение Python и публикацию серьезных и содержательных книг, имеющих отношение к программному обеспечению с открытыми исходными текстами

• Сообществу Python, составляющему большую часть моего мира начиная с 1992 года

• Тысячам студентов, прошедших через 250 курсов обучения языку Python, которые я провел начиная с 1997 года

• Сотням тысяч читателей, прочитавшим 12 изданий всех трех моих книг о Python, которые вышли с 1995 года

• Монти Пайтону (Monty Python), тезке Python, за множество интересных ситуаций, в которых есть чему поучиться (подробнее об этом - в следующей главе)

Книгу пишет обычно один человек, но многие идеи рождаются в сообществе. Я благодарен за отклики, которые мне повезло получить в течение последних 18 лет от моих студентов и читателей. Студенты - лучшие учителя учителей.

С личной стороны я хотел бы сказать спасибо моим братьям и сестре за старые добрые времена, а также моим детям, Майклу (Michael), Саманте (Samantha) и Роксане (Roxanne), за возможность гордиться ими.

А особенная благодарность моей супруге Вере (Vera), которой так или иначе удалось внести немало хорошего в этот в каком-то смысле неизменяемый объект.

Марк Лутц (Mark Lutz), июль 2010

Так что же такое Python?

Как уже говорилось выше, в этой книге не будет уделяться большое внимание основам Python, и мы отложим абстрактные рассуждения о роли Python до заключительной главы, то есть до того момента, когда вы познакомитесь с этим языком программирования на практике. Тем не менее если вы хотите получить исчерпывающее определение темы этой книги, извольте:

Python - это язык программирования общего назначения, распространяемый с открытыми исходными текстами (open source). Он оптимизирован для создания качественного программного обеспечения, высокой производительности труда разработчиков, переносимости программ и интеграции компонентов. Язык Python используется сотнями тысяч разработчиков по всему миру в таких областях, как создание веб-сценариев, системное программирование, создание пользовательских интерфейсов, настройка программных продуктов под пользователя, численное программирование и в других. Как считают многие, один из самых используемых языков программирования в мире.

Как популярный язык, обеспечивающий сокращение времени, затрачиваемого на разработку программ, Python используется для создания широкого круга программ в самых разных областях. В число пользователей Python в настоящее время входят Google, YouTube, Industrial Light & Magic, ESRI, системы BitTorrent обмена файлами, Jet Propulsion Lab в NASA, игра Eve Online и National Weather Service (национальная метеорологическая служба, США). Язык Python используется в самых разных областях, от администрирования систем, разработки веб-сайтов, создания сценариев для мобильных устройств и обучения, до тестирования аппаратуры, анализа капиталовложений, компьютерных игр и управления космическими кораблями.

Среди прочих достоинств, Python отличается удивительной простотой, удобочитаемостью и простым синтаксисом; он легко интегрируется с внешними компонентами, написанными на других языках программирования; имеет мультипарадигменную архитектуру и поддерживает объектно-ориентированное, функциональное и модульное программирование; обладает обширной коллекцией уже запрограммированных интерфейсов и утилит. Набор встроенных инструментальных средств делает его необычайно гибким и динамичным языком программирования, идеально подходящим не только для быстрого решения тактических задач, но и для разработки перспективных стратегических решений. Несмотря на свое общее назначение, Python часто называют языком сценариев, так как он позволяет легко и просто использовать другие программные компоненты и управлять ими.


Самым большим достоинством Python является, пожалуй, то, что с его помощью разработка программного обеспечения становится более быстрой и приятной. Есть такая категория людей, для которых программирование является самоцелью. Они наслаждаются самим процессом. Пишут программы исключительно для собственного удовольствия, а коммерческие или карьерные выгоды рассматривают лишь, как вторичное следствие. Именно такие люди в значительной степени причастны к появлению Интернета, движения за распространение программного обеспечения с открытыми исходными текстами (open source) и Python. Эти же люди исторически являются основными читателями этой книги. От них часто можно услышать, что с таким инструментом, как Python, программирование превращается в настоящее развлечение.

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


Об авторе

Марк Лутц (Mark Lutz) является ведущим специалистом в области обучения языку программирования Python, автором самых ранних и наиболее популярных публикаций и известен в сообществе пользователей Python своими новаторскими идеями.

Марк является автором книг «Изучаем Python», «Программирование на Python» и «Python Pocket Reference», выпущенных издательством O’Reilly, каждая из которых претерпела уже четыре издания. Он использует Python и занимается его популяризацией начиная с 1992 года; книги о Python начал писать в 1995 году; преподаванием этого языка программирования стал заниматься с 1997 года. На начало 2010 года Марк провел 250 курсов, обучил более 3500 студентов, написал книги по языку Python, суммарный тираж которых составил примерно четверть миллиона копий и которые были переведены более чем на десять языков.

Обладает степенями бакалавра и магистра в области информатики, закончи* университет штата Висконсин (США). На протяжении последних 25 лет занимался разработкой компиляторов, инструментальных средств программиста, приложений и разнообразных систем в архитектуре клиент/сервер. Связаться с Марком можно через веб-сайт книги http://rmi.net/~lutz и веб-сайт курсов, которые он ведет: http://learning-python.com.

I

Начало

Эта часть книги запускает повествование, предлагая краткий экскурс, в котором рассматриваются фундаментальные понятия языка Python и представляются некоторые из наиболее типичных приемов его использования.

Глава 1

Эта глава начинает рассказ с простого примера - записи информации о людях, - что позволит коротко представить некоторые из основных областей применения языка Python, которые мы будем изучать в этой книге. Мы заставим этот пример существовать в самых разных ситуациях. По пути мы встретимся с базами данных, графическими интерфейсами, веб-сайтами и так далее. Эта своего рода демонстрационная глава задумывалась с целью возбудить в вас интерес. Здесь мы не будем исследовать все аспекты, но у нас будет возможность увидеть Python в действии, прежде чем мы погрузимся в детали. Данная глава служит также обзором некоторых базовых идей языка, с которыми вы должны быть знакомы, прежде чем приступать к чтению этой книги, - такими как представление данных и объектно-ориентированное программирование (ООП).

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

1

Предварительный обзор


«Программирование на Python»: краткий очерк

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

Для этого я возьму довольно простое приложение, конструирующее базу данных, и проведу вас через различные этапы его создания: моделирование в интерактивном режиме, использование инструментов командной строки, создание интерфейса командной строки, создание графического интерфейса и создание простого веб-интерфейса. Попутно мы познакомимся с такими понятиями, как представление данных, сохранение объектов и объектно-ориентированное программирование (ООП); исследуем несколько альтернативных решений, к которым вернемся позднее; и рассмотрим некоторые основные идеи языка Python, которые вы должны знать, прежде чем продолжать чтение этой книги. В конечном итоге мы получим базу данных, хранящую экземпляры класса, которые можно будет просматривать и изменять с использованием различных интерфейсов.

Конечно, далее я затрону и дополнительные темы, но приемы, которые будут представлены здесь, применимы к некоторым прикладным областям, которые мы будем исследовать далее. Замечу также, что если что-то в программах из этой главы для вас останется непонятным, не волнуйтесь, так и должно быть - пока, по крайней мере. Здесь просто демонстрируются возможности Python. С недостающими подробностями вы познакомитесь достаточно скоро. А теперь начнем с небольшого развлечения.

Читатели четвертого издания книги «Изучаем Python» могут заметить в примере из этой главы знакомые черты - здесь участвуют те же персонажи, что и в главе про ООП в книге «Изучаем Python», а последние версии примера, основанные на использовании классов, по сути являются вариациями на ту же тему. Не боясь обвинений в избыточности, я здесь возвращаюсь к этому примеру по трем причинам: он вполне может использоваться для обзора основных возможностей языка; некоторые читатели этой книги не читали «Изучаем Python»; здесь этот пример получает дальнейшее развитие за счет добавления графического и веб-интерфейсов. Таким образом, эта глава начинается с того места, где закончилась книга «Изучаем Python», и помещает этот пример использования основных возможностей языка в контекст действующего приложения, что в общих чертах соответствует цели этой книги.


Постановка задачи

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

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


Шаг 1: представление записей

Коль скоро мы собрались сохранять записи в базе данных, на самом первом этапе нам необходимо решить, как будут выглядеть эти записи. В языке Python имеется масса способов представления информации о людях. Зачастую для этих целей вполне достаточно бывает использовать объекты встроенных типов, такие как списки и словари, особенно если изначально не требуется предусматривать обработку сохраняемых данных.


Списки

Списки, например, позволяют сохранять информацию о людях упорядоченным способом. Запустите интерпретатор Python в интерактивном режиме и введите следующие две инструкции:

>>> bob = [‘Bob Smith', 42, 30000, 'software']

>>> sue = [‘Sue Jones', 45, 40000, ‘hardware']

Мы только что создали две простые записи, представляющие информацию о Бобе (Bob) и Сью (Sue) (мои извинения, если вас действительно зовут Боб или Сью3). Каждая запись является списком с четырьмя элементами: имя, возраст, оклад и должность. Чтобы получить доступ к этим элементам, достаточно просто использовать операцию индексирования. Результат в примере ниже заключен в круглые скобки потому, что он является кортежем из двух результатов:

>>> bob[0], sue[2] # получить имя и оклад

(‘Bob Smith’, 40000)

В таком представлении записи легко обрабатывать - достаточно просто использовать операции над списками. Например, можно получить фамилию человека, разбив поле с именем по пробельному символу и отобрав последнюю часть, точно так же можно повысить оклад, изменив соответствующий список:

>>> bob[0].split()[-1] # получить фамилию Боба

‘Smith’

>>> sue[2] *= 1.25 # повысить оклад Сью на 25%

>>> sue

[‘Sue Jones’, 45, 50000.0, ‘hardware’]

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

Первые замечания

Поскольку это первый пример программного кода в книге, необходимо сделать несколько практических замечаний:

• Этот программный код можно ввести в среде IDLE с графическим интерфейсом; после ввода команды python в командной строке (или той же команды с указанием полного пути к ней, если она не находится в системном списке путей поиска выполняемых файлов) и так далее.

• Символы >>> characters - это приглашение к вводу интерпретатора Python (эти символы не нужно вводить).

• Информационные строки, которые интерпретатор Python выводит при запуске, я опустил ради экономии места.

• Все примеры из этой книги я запускал под управлением Python 3.1; результаты работы примеров во всех версиях линейки 3.X должны быть одинаковыми (разумеется, исключая непредвиденные случаи внесения существенных изменений в Python).

• Большая часть примеров в этой книге, за исключением некоторых из них, демонстрирующих приемы системного программирования и интеграции с программным кодом на языке C, выполнялись в ОС Windows 7. Однако, благодаря переносимости Python, не имеет значения, в какой операционной системе будут опробоваться примеры, если иное не указано явно.

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

База данных в виде списка

К настоящему моменту мы всего создали всего лишь две переменных, но не базу данных. Чтобы объединить информацию о Бобе и Сью, мы могли бы просто включить ее в другой список:

>>> people = [bob, sue] # ссылки в списке списков

>>> for person in people: print(person)

[‘Bob Smith’, 42, 30000, ‘software’]

[‘Sue Jones’, 45, 50000.0, ‘hardware’]

Теперь нашу базу данных представляет список people. Мы можем извлекать из него отдельные записи в соответствии с их позициями в списке и обрабатывать их в цикле:

>>> people[1][0]

‘Sue Jones’

>>> for person in people:

print(person[0].split()[-1]) # вывести фамилию

person[2] *= 1.20 # увеличить оклад на 20%

Smith

Jones

>>> for person in people: print(person[2]) # проверить новый размер оклада

36000.0

60000.0

Теперь, когда у нас имеется список, мы можем организовать выборку значений полей из записей с помощью более мощных инструментов выполнения итераций, присутствующих в языке Python, таких как генераторы списков, функция map и выражения-генераторы:

>>> pays = [person[2] for person in people] # выбрать все оклады >>> pays

[36000.0, 60000.0]

>>> pays = map((lambda x: x[2]), people) # то же самое (в версии 3.X

>>> list(pays) # функция map возвращает генератор)

[36000.0, 60000.0]

>>> sum(person[2] for person in people) # выражение-генератор,

96000.0 # sum - встроенная функция

Для добавления новых записей в базу данных вполне достаточно использовать обычные операции над списками, такие как append и extend:

>>> people.append(['Tom', 50, 0, None])

>>> len(people)

3

>>> people[-1][0]

‘Tom’

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

Обращение к полям по именам

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

Мы могли бы связать имена с позициями полей в записи, используя встроенную функцию range, которая генерирует набор последовательных целых чисел при использовании в контексте итераций (таких как операция присваивания последовательности ниже):

>>> NAME, AGE, PAY = range(3) # 0, 1 и 2

>>> bob = ['Bob Smith’, 42, 10000]

>>> bob[NAME]

‘Bob Smith’

>>> PAY, bob[PAY]

(2, 10000)

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

Кроме того, так как имена полей являются независимыми переменными, между записью в виде списка и именами полей отсутствует обратная связь. Имея одну только запись в виде списка, например, нельзя реализовать форматированный вывод значений полей с их именами. В случае с предыдущей записью без дополнительных ухищрений невозможно получить имя AGE из значения 42: вызов bob.index(42) вернет 1, значение переменной AGE, но не само имя AGE.

Можно было бы попробовать представлять записи в виде списков кортежей, где кортежи хранят не только значения полей, но их имена. Но еще лучше было бы использовать списки списков, что позволило бы изменять поля (кортежи относятся к категории неизменяемых объектов). Ниже демонстрируется воплощение этой идеи на примере простых записей:

>>> bob = [['name', ‘Bob Smith'], ['age', 42], ['pay', 10000]]

>>> sue = [['name', ‘Sue Jones'], ['age', 45], ['pay', 20000]]

>>> people = [bob, sue]

Однако на самом деле этот прием не решает проблему, потому что для извлечения полей все равно необходимо использовать числовые индексы:

>>> for person in people:

print(person[0][1], person[2][1]) # имя, оклад

Bob Smith 10000 Sue Jones 20000

>>> [person[0][1] for person in people] # выборка имен [‘Bob Smith’, ‘Sue Jones’]

>>> for person in people:

print(person[0][1].split()[-1]) # получить фамилию person[2][1] *= 1.10 # повысить оклад на 10%

Smith

Jones

>>> for person in people: print(person[2])

[‘pay’, 11000.0]

[‘pay’, 22000.0]

Все, чего мы добились, - добавили еще один уровень индексирования. Для достижения желаемого мы могли бы просматривать имена полей в цикле, отыскивая необходимые (в следующем цикле используется операция присваивания кортежа для распаковывания пар имя/значение):

>>> for person in people:

for (name, value) in person:

if name == ‘name': print(value) # поиск требуемого поля

Bob Smith Sue Jones

Еще лучше было бы реализовать функцию, выполняющую всю работу за нас:

>>> def field(record, label):

for (fname, fvalue) in record:

if fname == label: # поиск поля по имени

return fvalue

>>> field(bob, ‘name')

‘Bob Smith’

>>> field(sue, ‘pay')

22000.0

>>> for rec in people: # вывести возраст всех людей

print(field(rec, ‘age')) # в базе данных

42

45

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


Словари

Реализация записей на основе списков, как было показано в предыдущем разделе, вполне работоспособна, хотя и за счет некоторой потери производительности из-за необходимости выполнять поиск полей по именам (если вас волнуют потери, измеряемые миллисекундами). Однако если вы уже имеете некоторое знакомство с языком Python, вы должны знать, что существуют более эффективные и более удобные способы связывания имен полей с их значениями. Встроенные объекты словарей выглядят естественно:

>>> bob = {‘name': ‘Bob Smith', ‘age': 42, ‘pay': 30000, ‘job': ‘dev'}

>>> sue = {‘name': ‘Sue Jones', ‘age': 45, ‘pay': 40000, ‘job': ‘hdw'}

Теперь bob и sue - это объекты, автоматически отображающие имена полей в их значения, и их использование делает программный код более простым и понятным. Нам не требуется запоминать, что означают числовые индексы, и мы даем интерпретатору возможность использовать его высокоэффективный алгоритм индексации словарей, чтобы отыскивать значения полей, ассоциированные с их именами:

>>> bob[‘name'], sue[‘pay'] # в отличие от bob[0], sue[2]

(‘Bob Smith’, 40000)

>>> bob[‘name'].split()[-1]

‘Smith’

>>> sue[‘pay'] *= 1.10

>>> sue[‘pay']

44000.0

Поскольку теперь при обращении к полям используются символические имена, программный код выглядит более осмысленным для всех, кто будет читать его (включая и вас).

Другие способы создания словарей

Словари являются настолько удобными объектами при программировании на языке Python, что было предусмотрено еще несколько способов их создания, отличающихся от традиционного синтаксиса литералов, продемонстрированного выше, - например, вызовом конструктора с именованными аргументами, при этом все ключи будут строками:

>>> bob = dict(name='Bob Smith', age=42, pay=30000, job='dev')

>>> sue = dict(name='Sue Jones', age=45, pay=40000, job='hdw')

>>> bob

{‘pay’: 30000, ‘job’: ‘dev’, ‘age’: 42, ‘name’: ‘Bob Smith’}

>>> sue

{‘pay’: 40000, ‘job’: ‘hdw’, ‘age’: 45, ‘name’: ‘Sue Jones’}

заполнением словаря поле за полем (напомню, что для ключей словаря не предусматривается какой-то определенный порядок следования):

>>> sue = {}

>>> sue[‘name'] = ‘Sue Jones'

>>> sue[‘age'] = 45 >>> sue[‘pay'] = 40000 >>> sue[‘job'] = ‘hdw'

>>> sue

{‘job’: ‘hdw’, ‘pay’: 40000, ‘age’: 45, ‘name’: ‘Sue Jones’}

объединением двух списков, содержащих имена и значения:

>>> names = [‘name', ‘age', ‘pay', ‘job']

>>> values = [‘Sue Jones', 45, 40000, ‘hdw']

>>> list(zip(names, values))

[(‘name’, ‘Sue Jones’), (‘age’, 45), (‘pay’, 40000), (‘job’, ‘hdw’)]

>>> sue = dict(zip(names, values))

>>> sue

{‘job’: ‘hdw’, ‘pay’: 40000, ‘age’: 45, ‘name’: ‘Sue Jones’}

Словари можно даже создавать из последовательностей ключей и необязательного начального значения для всех ключей (этот способ удобно использовать для инициализации пустых словарей):

>>> fields = (‘name', ‘age', ‘job', ‘pay')

>>> record = dict.fromkeys(fields, ‘?')

>>> record

{‘job’: ‘?’, ‘pay’: ‘?’, ‘age’: ‘?’, ‘name’: ‘?’}

Списки словарей

Независимо от способа создания словарей, нам все еще необходимо собрать словари-записи в базу данных. Здесь также можно использовать список, при условии, что нам не требуется обеспечить доступ по ключу на верхнем уровне:

>>> bob

{‘pay’: 30000, ‘job’: ‘dev’, ‘age’: 42, ‘name’: ‘Bob Smith’}

>>> sue

{‘job’: ‘hdw’, ‘pay’: 40000, ‘age’: 45, ‘name’: ‘Sue Jones’}

>>> people = [bob, sue] # ссылки в списке

>>> for person in people:

print(person[‘name'], person[‘pay'], sep=', ‘) # все имена, оклады

Bob Smith, 30000 Sue Jones, 40000

>>> for person in people:

if person[‘name'] == ‘Sue Jones': # оклад Сью

print(person[‘pay'])

40000

Здесь точно так же используются инструменты итераций, но вместо таинственных числовых индексов используются ключи (в терминах баз данных генератор списков и функция map в следующем примере возвращают проекцию базы данных по полю «name»):

>>> names = [person[‘name'] for person in people] # выбирает имена >>> names

[‘Bob Smith’, ‘Sue Jones’]

>>> list(map((lambda x: x[‘name']), people)) # то же самое

[‘Bob Smith’, ‘Sue Jones’]

>>> sum(person[‘pay'] for person in people) # сумма всех окладов

70000

Интересно, что такие инструменты, как генераторы списков и выражения-генераторы, способны по своему удобству приблизиться к запросам в языке SQL, с тем отличием, что они манипулируют объектами в памяти:

>>> [rec[‘name'] for rec in people if rec[‘age'] >= 45] # SQL-подобный

[‘Sue Jones’] # запрос

>>> [(rec[‘age'] ** 2 if rec[‘age'] >= 45 else rec[‘age']) for rec in people]

[42, 2025] >>> G = (rec[‘name'] for rec in people if rec[‘age'] >= 45)

>>> next(G)

‘Sue Jones’

>>> G = ((rec[‘age'] ** 2 if rec[‘age'] >= 45 else rec[‘age']) for rec in people)

>>> G.__next__()

42

А так как словари являются обычными объектами, к этим записям можно также обращаться с использованием привычного синтаксиса:

>>> for person in people:

print(person[‘name'].split()[-1]) # фамилия

person[‘pay'] *= 1.10 # повышение на 10%

Smith

Jones

>>> for person in people: print(person[‘pay'])

33000.0

44000.0

Вложенные структуры

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

В следующем примере демонстрируется более структурированная запись, содержащая вложенный словарь, список и кортеж внутри другого словаря:

>>> bob2 = {‘name': {‘first': ‘Bob', ‘last': ‘Smith'},

‘age': 42,

‘job': [‘software', ‘writing'],

‘pay': (40000, 50000)}

Эта запись содержит вложенные структуры, поэтому для доступа к более низкому уровню мы просто будем использовать двойные индексы:

>>> bob2[‘name'] # полное имя Боба

{‘last’: ‘Smith’, ‘first’: ‘Bob’}

>>> bob2[‘name'][‘last'] # фамилия Боба

‘Smith’

>>> bob2[‘pay'][1] # верхний предел оклада Боба

50000

Поле name здесь - это еще один словарь, поэтому вместо того чтобы разбивать строку для извлечения фамилии, мы просто используем операцию индексирования. Кроме того, сотрудники могут занимать несколько должностей, а также иметь верхний и нижний предел оклада. Фактически в подобных ситуациях Python превращается в своеобразный язык запросов - мы можем извлекать и изменять вложенные значения с применением обычных операций над объектами:

>>> for job in bob2[‘job']: print(job) # все должности, занимаемые Бобом

software

writing

>> bob2[‘job'][-1] # последняя должность Боба

‘writing’

>>> bob2[‘job'].append(‘janitor') # Боб получает новую должность >>> bob2

{‘job’: [‘software’, ‘writing’, ‘janitor’], ‘pay’: (40000, 50000), ‘age’: 42, ‘name’: {‘last’: ‘Smith’, ‘first’: ‘Bob’}}

В расширении вложенного списка с помощью метода append нет ничего необычного, потому что в действительности он является независимым объектом. Такие вложенные конструкции могут пригодиться в более сложных приложениях. Однако, чтобы не усложнять примеры, мы сохраним прежнюю, плоскую структуру записей.

Словари словарей

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

>>> bob = dict(name='Bob Smith', age=42, pay=30000, job='dev')

>>> sue = dict(name='Sue Jones', age=45, pay=40000, job='hdw')

>>> bob

{‘pay’: 30000, ‘job’: ‘dev’, ‘age’: 42, ‘name’: ‘Bob Smith’}

>>> db = {}

>>> db[‘bob'] = bob # ссылки на словари в словаре

>>> db[‘sue'] = sue

>>>

>>> db[‘bob'][‘name'] # извлечь имя Боба

‘Bob Smith’

>>> db[‘sue'][‘pay'] = 50000 # изменить оклад Сью

>>> db[‘sue'][‘pay'] # извлечь оклад Сью

50000

Обратите внимание, что такая организация позволяет нам обращаться к записям непосредственно, без необходимости выполнять поиск в цикле - мы получаем непосредственный доступ к записи с информацией о Бобе за счет использования ключа bob. Это действительно словарь словарей, хотя это и не заметно, если не вывести всю базу данных сразу (для подобных целей удобно использовать модуль pprint форматированного вывода):

>>> db

{‘bob’: {‘pay’: 30000, ‘job’: ‘dev’, ‘age’: 42, ‘name’: ‘Bob Smith’}, ‘sue’: {‘pay’: 50000, ‘job’: ‘hdw’, ‘age’: 45, ‘name’: ‘Sue Jones’}}

>>> import pprint >>> pprint.pprint(db)

{‘bob’: {‘age’: 42, ‘job’: ‘dev’, ‘name’: ‘Bob Smith’, ‘pay’: 30000},

‘sue’: {‘age’: 45, ‘job’: ‘hdw’, ‘name’: ‘Sue Jones’, ‘pay’: 50000}}

Если же возникнет необходимость последовательно обойти все записи в базе данных, можно воспользоваться итераторами словарей. В последних версиях Python реализован итератор словаря, который на каждой итерации в цикле for воспроизводит по одному ключу (для совместимости с более ранними версиями в циклах for можно также вместо простого имени db использовать явный вызов метода db. keys, но, так как в Python 3 метод keys возвращает генератор, конечный результат будет тот же самый):

>>> for key in db:

print(key, ‘=>', db[key][‘name'])

bob => Bob Smith sue => Sue Jones

>>> for key in db:

print(key, ‘=>', db[key][‘pay'])

bob => 30000 sue => 50000

В процессе обхода доступ к отдельным записям можно получать с использованием операции индексирования по ключу:

>>> for key in db:

print(db[key][‘name'].split()[-1]) db[key][‘pay'] *= 1.10

Smith

Jones

или напрямую, организовав обход значений словаря:

>>> for record in db.values(): print(record[‘pay'])

33000.0

55000.0

>>> x = [db[key][‘name'] for key in db]

>>> x

[‘Bob Smith’, ‘Sue Jones’]

>>> x = [rec[‘name'] for rec in db.values()]

>>> x

[‘Bob Smith’, ‘Sue Jones’]

А чтобы добавить новую запись, достаточно просто выполнить операцию присваивания по новому ключу. В конце концов - это всего лишь словарь:

>>> db[‘tom'] = dict(name='Tom', age=50, job=None, pay=0)

>>>

>>> db[‘tom']

{‘pay’: 0, ‘job’: None, ‘age’: 50, ‘name’: ‘Tom’}

>>> db[‘tom'][‘name']

‘Tom’

>>> list(db.keys())

[‘bob’, ‘sue’, ‘tom’]

>>> len(db)

3

>>> [rec[‘age'] for rec in db.values()]

[42, 45, 50]

>>> [rec[‘name'] for rec in db.values() if rec[‘age'] >= 45] # SQL-подобный [‘Sue Jones’, ‘Tom’] # запрос

Наша база данных по-прежнему является объектом, хранящимся в оперативной памяти. Но, как оказывается, такой формат словаря словарей в точности соответствует формату, который используется системой сохранения объектов в файлах, - модулем shelve (с точки зрения грамматики английского языка этот модуль должен был бы называться shelf, но в Python термин shelve, обозначающий сохранение объектов, одновременно служит и названием соответствующего ему модуля). О том, как это делается, вы узнаете в следующем разделе.


Шаг 2: сохранение записей на длительное время

К настоящему моменту мы остановились на представлении нашей базы данных в виде словаря и попутно рассмотрели некоторые способы реализации структур данных в языке Python. Однако, как уже упоминалось выше, объекты, с которыми мы имели дело до сих пор, - временные объекты; они располагаются в оперативной памяти и исчезают бесследно после завершения работы интерпретатора Python или программы, создавшей их. Чтобы обеспечить долговременное хранение базы данных, ее необходимо сохранить в каком-нибудь файле.


Текстовые файлы

Один из способов обеспечить сохранность данных между запусками программы заключается в сохранении всех данных в простом файле, в виде отформатированного текста. Выработав определенную договоренность о формате представления данных, которая будет использоваться инструментами чтения и записи, мы сможем реализовать любую схему хранения.

Тестовый сценарий создания данных

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

Пример 1.1. PP4E\Preview\initdata.py

# инициализировать данные для последующего сохранения в файлах

# записи

bob = {‘name’: ‘Bob Smith’, ‘age’: 42, ‘pay’: 30000, ‘job’: ‘dev’}

sue = {‘name’: ‘Sue Jones’, ‘age’: 45, ‘pay’: 40000, ‘job’: ‘hdw’}

tom = {‘name’: ‘Tom’, ‘age’: 50, ‘pay’: 0, ‘job’: None}

# база данных db = {}

db[‘bob’] = bob db[‘sue’] = sue db[‘tom’] = tom

if __name__ == ‘__main__’: # если запускается, как сценарий

for key in db:

print(key, ‘=>\n ‘, db[key])

Как обычно, проверка переменной__name__в конце примера 1.1 возвра

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

Ниже приводится пример запуска сценария из командной строки в ОС Windows. В окне Командная строка (Command Prompt) выполните команду cd, чтобы перейти в каталог со сценарием. На других платформах используйте аналогичную программу-консоль:

...\PP4E\Preview> python initdata.py

bob =>

{‘job’: ‘dev’, ‘pay’: 30000, ‘age’: 42, ‘name’: ‘Bob Smith’}

sue =>

{‘job’: ‘hdw’, ‘pay’: 40000, ‘age’: 45, ‘name’: ‘Sue Jones’} tom =>

{‘job’: None, ‘pay’: 0, ‘age’: 50, ‘name’: ‘Tom’}

Соглашения об именовании файлов

Это наш первый файл (он же «сценарий») с исходными текстами, поэтому здесь необходимо сделать три замечания по использованию примеров из книги:

• Текст .. .\PP4E\Preview> в первой строке предыдущего примера обозначает приглашение к вводу в командной строке и может отличаться в разных платформах. Вам необходимо ввести лишь текст, следующий за этим приглашением (python initdata.py).

• Во всех примерах в этой книге текст системной подсказки к вводу содержит путь к каталогу в загружаемом пакете с примерами, внутри которого должна запускаться указанная команда. При запуске сценария из командной строки убедитесь, что текущим рабочим каталогом является каталог PP4E\Preview. Это может иметь значение для примеров, использующих файлы в рабочем каталоге.

Загрузка...