Содержание страницы
Что нового в Python 2.0¶What’s New in Python 2.0
- Автор
A.M. Kuchling and Moshe Zadka
Введение¶Introduction
Новый выпуск Python, версия 2.0, был выпущен 16 октября 2000 года. В этой статье рассматриваются захватывающие новые возможности версии 2.0, освещаются некоторые другие полезные изменения и указываются несколько несовместимых изменений, которые могут потребовать переписывания кода.
Разработка Python никогда не прекращается полностью между релизами – в неё постоянно поступает непрерывный поток исправлений ошибок и улучшений. В версию 2.0 вошло множество мелких исправлений, несколько оптимизаций, дополнительные строки документации и более качественные сообщения об ошибках; перечислить их все невозможно, но они, безусловно, важны. Если хотите увидеть полный список, обратитесь к общедоступным журналам CVS. Этот прогресс стал возможен благодаря пяти разработчикам, работающим в PythonLabs, которые теперь получают зарплату за то, что целыми днями исправляют ошибки, а также благодаря улучшению коммуникации после перехода на SourceForge.
Что насчёт Python 1.6?¶What About Python 1.6?
Python 1.6 можно считать релизом Python по договорным обязательствам. После того как основная команда разработчиков покинула CNRI в мае 2000 года, CNRI потребовала создать релиз 1.6, содержащий всю работу над Python, которая была выполнена в CNRI. Таким образом, Python 1.6 представляет состояние дерева CVS по состоянию на май 2000 года, причём наиболее значимой новой функцией является поддержка Unicode. Разработка, конечно, продолжалась и после мая, поэтому дерево 1.6 получило несколько исправлений для обеспечения прямой совместимости с Python 2.0. Поэтому 1.6 является частью эволюции Python, а не побочной ветвью.
Стоит ли проявлять большой интерес к Python 1.6? Вероятно, нет. Релизы 1.6final и 2.0beta1 вышли в один день (5 сентября 2000 года), и планировалось завершить Python 2.0 примерно через месяц. Если у вас есть приложения, которые нужно поддерживать, то вряд ли есть смысл всё ломать переходом на 1.6, исправлять их, а затем снова ломать через месяц переходом на 2.0; лучше сразу перейти на 2.0. Большинство действительно интересных функций, описанных в этом документе, есть только в 2.0, потому что между маем и сентябрём было проделано много работы.
Новый процесс разработки¶New Development Process
Самое важное изменение в Python 2.0 может относиться вовсе не к коду, а к тому, как разрабатывается Python: в мае 2000 года разработчики Python начали использовать инструменты, предоставляемые SourceForge, для хранения исходного кода, отслеживания сообщений об ошибках и управления очередью патчей. Чтобы сообщить об ошибке или отправить патч для Python 2.0, используйте систему отслеживания ошибок и менеджер патчей, доступные на странице проекта Python по адресу https://sourceforge.net/projects/python/.
Самая важная из служб, теперь размещённых на SourceForge, – это дерево CVS Python, репозиторий с контролем версий, содержащий исходный код Python. Раньше доступ на запись к дереву CVS имели примерно 7 человек, и все патчи должен был просматривать и принимать один из участников этого короткого списка. Очевидно, это было не очень масштабируемо. Перенеся дерево CVS на SourceForge, стало возможным предоставить доступ на запись большему числу людей; по состоянию на сентябрь 2000 года 27 человек могли вносить изменения, что в четыре раза больше. Это делает возможными крупномасштабные изменения, которые не были бы предприняты, если бы их приходилось фильтровать через небольшую группу основных разработчиков. Например, однажды Петер Шнайдер-Камп решил отказаться от совместимости с K&R C и преобразовать исходный код C для Python в ANSI C. Получив одобрение в списке рассылки python-dev, он начал серию коммитов, которая длилась около недели, к нему присоединились другие разработчики, и работа была выполнена. Если бы доступ на запись был только у 5 человек, вероятно, эта задача была бы сочтена «хорошей, но не стоящей затрат времени и усилий» и никогда не была бы выполнена.
Переход на использование служб SourceForge привёл к заметному увеличению скорости разработки. Теперь патчи отправляются, комментируются, дорабатываются людьми, отличными от первоначального отправителя, и пересылаются между людьми до тех пор, пока патч не будет признан достойным включения. Ошибки отслеживаются в одном центральном месте и могут быть назначены конкретному человеку для исправления, и мы можем подсчитывать количество открытых ошибок для измерения прогресса. Это не обошлось без затрат: теперь разработчикам приходится иметь дело с большим объёмом электронной почты, следить за большим количеством списков рассылки, и для новой среды пришлось написать специальные инструменты. Например, SourceForge отправляет стандартные уведомления о патчах и ошибках, которые совершенно бесполезны, поэтому Ка-Пинг Йи написал HTML-скрейпер, который отправляет более полезные сообщения.
Лёгкость добавления кода вызвала некоторые первоначальные трудности роста, например, код принимался до того, как был готов, или без чёткого согласия группы разработчиков. Процесс утверждения, который возник, несколько похож на тот, что используется в группе Apache. Разработчики могут голосовать +1, +0, -0 или -1 за патч; +1 и -1 означают принятие или отклонение, тогда как +0 и -0 означают, что разработчику в основном безразлично это изменение, хотя с лёгким положительным или отрицательным оттенком. Наиболее существенное отличие от модели Apache заключается в том, что голосование носит в основном рекомендательный характер, позволяя Гвидо ван Россуму, имеющему статус Benevolent Dictator For Life (великодушный пожизненный диктатор), узнать общее мнение. Он всё ещё может игнорировать результаты голосования и одобрять или отклонять изменения, даже если сообщество с ним не согласно.
Создание готового патча – последний шаг при добавлении новой возможности, и обычно он проще, чем предшествующая задача разработки хорошего дизайна. Обсуждения новых возможностей нередко раздуваются до длинных обсуждений в списках рассылки, из-за чего за обсуждением становится трудно следить; да и никто не может прочитать каждое сообщение в python-dev. Поэтому был создан относительно формальный процесс написания предложений по улучшению Python (PEP), построенный по образцу процесса RFC в Интернете. PEP – это черновые документы, описывающие предлагаемую новую возможность; они постоянно дорабатываются, пока сообщество не придет к консенсусу, принимая или отклоняя предложение. Цитируя введение к PEP 1, “PEP Purpose and Guidelines”:
PEP означает Python Enhancement Proposal (предложение по улучшению Python). PEP – это проектный документ, предоставляющий информацию сообществу Python или описывающий новую возможность для Python. PEP должен содержать краткую техническую спецификацию функции и обоснование этой функции.
Мы предполагаем, что PEP будут основным механизмом предложения новых функций, сбора мнений сообщества по вопросу и документирования проектных решений, принятых в Python. Автор PEP отвечает за достижение консенсуса в сообществе и документирование разногласий.
Остальную часть PEP 1 читайте для получения подробностей о редакционном процессе, стиле и формате. PEP хранятся в дереве CVS Python на SourceForge, хотя они не являются частью дистрибутива Python 2.0, и также доступны в HTML-форме по адресу https://www.python.org/dev/peps/. По состоянию на сентябрь 2000 года существует 25 PEP, от PEP 201, “Lockstep Iteration”, до PEP 225, “Elementwise/Objectwise Operators”.
Юникод¶Unicode
Самая большая новая функция в Python 2.0 – это новый фундаментальный тип данных: строки Unicode. В Unicode для представления символов используются 16-битные числа вместо 8-битных, используемых в ASCII, что означает поддержку 65 536 различных символов.
Окончательный интерфейс поддержки Unicode был достигнут в результате бесчисленных, часто бурных обсуждений в списке рассылки python-dev и в основном реализован Марком-Андре Лембургом на основе реализации строкового типа Unicode Фредрика Лунда. Подробное объяснение интерфейса было записано в PEP 100, «Python Unicode Integration» (Интеграция Unicode в Python). Эта статья лишь охватывает наиболее важные моменты, касающиеся интерфейсов Unicode.
В исходном коде Python строки Unicode записываются как u"string". Произвольные символы Unicode можно записать с помощью новой управляющей последовательности \uHHHH, где HHHH – это 4-значное шестнадцатеричное число от 0000 до FFFF. Существующую управляющую последовательность \xHHHH также можно использовать, а восьмеричные escape-последовательности можно использовать для символов до U+01FF, который представляется как \777.
Строки Unicode, как и обычные строки, являются неизменяемым типом последовательности. Их можно индексировать и нарезать, но нельзя изменять на месте. Строки Unicode имеют метод encode( [encoding] ), который возвращает 8-битную строку в нужной кодировке. Кодировки задаются строками, такими как 'ascii', 'utf-8', 'iso-8859-1' и т.д. Для реализации и регистрации новых кодировок определён API codec, после чего они становятся доступны во всей программе Python. Если кодировка не указана, по умолчанию обычно используется 7-битная ASCII, хотя её можно изменить для вашей установки Python, вызвав функцию sys.setdefaultencoding(encoding) в настроенной версии site.py.
Объединение 8-битных строк и строк Unicode всегда приводит к Unicode с использованием кодировки ASCII по умолчанию; результатом 'a' + u'bc' является u'abc'.
Были добавлены новые встроенные функции, а существующие встроенные функции изменены для поддержки Unicode:
unichr(ch)возвращает строку Unicode длиной в 1 символ, содержащую символ ch.ord(u), где u – это односимвольная обычная или Unicode-строка, возвращает номер символа в виде целого числа.unicode(string [, encoding] [, errors] )создаёт строку Unicode из 8-битной строки.encoding– это строка, указывающая используемую кодировку. Параметрerrorsзадаёт обработку символов, недействительных для текущей кодировки; передача'strict'в качестве значения вызывает исключение при любой ошибке кодирования, тогда как'ignore'приводит к игнорированию ошибок, а'replace'в случае проблем использует U+FFFD – официальный замещающий символ.Оператор
exec, а также различные встроенные функции, такие какeval(),getattr()иsetattr(), также принимают строки Unicode наряду с обычными строками. (Возможно, в процессе исправления были пропущены некоторые встроенные функции; если вы найдёте встроенную функцию, которая принимает строки, но совсем не принимает строки Unicode, сообщите об этом как об ошибке.)
Новый модуль unicodedata предоставляет интерфейс к свойствам символов Unicode. Например, unicodedata.category(u'A') возвращает двухсимвольную строку 'Lu', где 'L' обозначает, что это буква, а 'u' – заглавная. unicodedata.bidirectional(u'\u0660') возвращает 'AN', что означает, что U+0660 – арабская цифра.
Модуль codecs содержит функции для поиска существующих кодировок и регистрации новых. Если вы не хотите реализовывать новую кодировку, вы чаще всего будете использовать функцию codecs.lookup(encoding), которая возвращает кортеж из 4 элементов: (encode_func, decode_func, stream_reader, stream_writer).
encode_func – это функция, принимающая строку Unicode и возвращающая кортеж из двух элементов
(string, length). string представляет собой 8-битную строку, содержащую часть (возможно, всю) строки Unicode, преобразованную в заданную кодировку, а length показывает, какая часть строки Unicode была преобразована.decode_func – это противоположность encode_func: она принимает 8-битную строку и возвращает кортеж из двух элементов
(ustring, length), состоящий из результирующей строки Unicode ustring и целого числа length, указывающего, какая часть 8-битной строки была обработана.stream_reader – это класс, который поддерживает декодирование входных данных из потока. stream_reader(file_obj) возвращает объект, поддерживающий методы
read(),readline()иreadlines(). Все эти методы выполняют преобразование из заданной кодировки и возвращают строки Unicode.stream_writer, аналогично, – это класс, который поддерживает кодирование выходных данных в поток. stream_writer(file_obj) возвращает объект, поддерживающий методы
write()иwritelines(). Эти методы ожидают строки Unicode, преобразуя их в заданную кодировку при выводе.
Например, следующий код записывает строку Unicode в файл, кодируя её в UTF-8:
import codecs
unistr = u'\u0660\u2000ab ...'
(UTF8_encode, UTF8_decode,
UTF8_streamreader, UTF8_streamwriter) = codecs.lookup('UTF-8')
output = UTF8_streamwriter( open( '/tmp/output', 'wb') )
output.write( unistr )
output.close()
Следующий код затем читает входные данные в UTF-8 из файла:
input = UTF8_streamreader( open( '/tmp/output', 'rb') )
print repr(input.read())
input.close()
Регулярные выражения с поддержкой Unicode доступны через модуль re, у которого появилась новая внутренняя реализация под названием SRE, написанная Фредриком Лундом из Secret Labs AB.
Был добавлен параметр командной строки -U, заставляющий компилятор Python интерпретировать все строковые литералы как литералы Unicode. Это предназначено для использования при тестировании и подготовке кода к будущим изменениям, поскольку в одной из будущих версий Python может быть прекращена поддержка 8-битных строк и оставлены только строки Unicode.
Списочные включения¶List Comprehensions
Списки – это основной тип данных в Python, и многие программы так или иначе работают со списками. Две распространённые операции над списками – это перебор элементов с выбором тех, которые удовлетворяют определённому условию, или применение некоторой функции к каждому элементу. Например, имея список строк, можно захотеть извлечь все строки, содержащие заданную подстроку, или удалить завершающие пробелы в каждой строке.
Существующие функции map() и filter() можно использовать для этой цели, но они требуют функцию в качестве одного из своих аргументов. Это нормально, если есть готовая встроенная функция, которую можно передать напрямую. Если же такой функции нет, приходится создавать небольшую функцию для выполнения нужной работы, и правила областей видимости Python делают результат некрасивым, если такая мини-функция требует дополнительной информации. Возьмём первый пример из предыдущего абзаца: поиск всех строк в списке, содержащих заданную подстроку. Для этого можно написать следующий код:
# По списку L создать список всех строк
# содержащих подстроку S.
sublist = filter( lambda s, substring=S:
string.find(s, substring) != -1,
L)
Из-за правил области видимости в Python используется аргумент по умолчанию, чтобы
анонимная функция, созданная оператором lambda, знала, какая подстрока ищется. Списковые включения делают это более понятно:
sublist = [ s for s in L if string.find(s, S) != -1 ]
Списочные включения имеют следующий вид:
[ expression for expr in sequence1
for expr2 in sequence2 ...
for exprN in sequenceN
if condition ]
Предложения for…in содержат последовательности, по которым выполняется итерация. Последовательности не обязаны быть одинаковой длины, поскольку они не итерируются параллельно, а слева направо; это более подробно объясняется в следующих абзацах. Элементами результирующего списка будут последовательные значения expression. Последнее предложение if является необязательным; если оно присутствует, то expression вычисляется и добавляется в результат только в том случае, если condition истинно.
Чтобы прояснить семантику, списочное включение эквивалентно следующему коду Python:
for expr1 in sequence1:
for expr2 in sequence2:
...
for exprN in sequenceN:
if (condition):
# Добавить значение
# выражения в
# результирующий список.
Это означает, что при наличии нескольких предложений for…in результирующий список будет равен произведению длин всех последовательностей. Если есть два списка длины 3, выходной список будет состоять из 9 элементов:
seq1 = 'abc'
seq2 = (1,2,3)
>>> [ (x,y) for x in seq1 for y in seq2]
[('a', 1), ('a', 2), ('a', 3), ('b', 1), ('b', 2), ('b', 3), ('c', 1),
('c', 2), ('c', 3)]
Чтобы избежать неоднозначности в грамматике Python, если expression создаёт кортеж, его необходимо окружить круглыми скобками. Первое списочное включение ниже содержит синтаксическую ошибку, тогда как второе – корректно:
# Синтаксическая ошибка
[ x,y for x in seq1 for y in seq2]
# Верно
[ (x,y) for x in seq1 for y in seq2]
Идея списочных включений изначально пришла из функционального языка программирования Haskell (https://www.haskell.org). Грег Юинг наиболее убедительно аргументировал их добавление в Python и написал начальный патч для списочных включений, который затем обсуждался, казалось, бесконечно долго в списке рассылки python-dev и поддерживался в актуальном состоянии Скипом Монтанаро.
Составное присваивание¶Augmented Assignment
Операторы составного присваивания, ещё одна давно запрашиваемая возможность, были добавлены в Python 2.0. Операторы составного присваивания включают +=, -=, *= и так далее. Например, оператор a += 2 увеличивает значение переменной a на 2, что эквивалентно чуть более длинной записи a = a + 2.
Полный список поддерживаемых операторов присваивания: +=, -=, *=, /=, %=, **=, &=, |=, ^=, >>= и <<=. Классы Python могут переопределять операторы составного присваивания, определяя методы с именами __iadd__(), __isub__() и т.д. Например, следующий класс Number хранит число и поддерживает использование += для создания нового экземпляра с увеличенным значением.
class Number:
def __init__(self, value):
self.value = value
def __iadd__(self, increment):
return Number( self.value + increment)
n = Number(5)
n += 3
print n.value
Специальный метод __iadd__() вызывается со значением приращения и должен возвращать новый экземпляр с соответствующим образом изменённым значением; это возвращаемое значение становится новым значением переменной в левой части.
Операторы составного присваивания были впервые введены в языке программирования C, и большинство языков, производных от C, такие как awk, C++, Java, Perl и PHP, также их поддерживают. Патч для составного присваивания был реализован Томасом Ваутерсом.
Методы строк¶String Methods
До сих пор функциональность для работы со строками находилась в модуле string, который обычно был обёрткой для модуля strop, написанного на C. Добавление Unicode создало трудность для модуля strop, поскольку все функции нужно было бы переписать, чтобы они принимали как 8-битные, так и Unicode-строки. Для таких функций, как string.replace(), принимающей 3 строковых аргумента, это означает восемь возможных комбинаций и, соответственно, сложный код.
Вместо этого Python 2.0 перекладывает проблему на строковый тип, делая функциональность для работы со строками доступной через методы как для 8-битных строк, так и для строк Unicode.
>>> 'andrew'.capitalize()
'Andrew'
>>> 'hostname'.replace('os', 'linux')
'hlinuxtname'
>>> 'moshe'.find('sh')
2
Одна вещь, которая не изменилась, несмотря на известную первоапрельскую шутку, – это то, что строки Python неизменяемы. Таким образом, строковые методы возвращают новые строки и не изменяют строку, к которой они применяются.
Старый модуль string всё ещё существует для обратной совместимости, но в основном он действует как обёртка для новых строковых методов.
Два метода, не имеющих аналогов в версиях до 2.0, хотя они уже некоторое время существовали в JPython, – это startswith() и endswith(). s.startswith(t) эквивалентен s[:len(t)] == t, а s.endswith(t) эквивалентен s[-len(t):] == t.
Ещё один метод, заслуживающий особого упоминания, – это join(). Метод join() строки принимает один параметр – последовательность строк – и эквивалентен функции string.join() из старого модуля string, но с обратным порядком аргументов. Другими словами, s.join(seq) эквивалентен старому string.join(seq, s).
Сборка мусора циклических ссылок¶Garbage Collection of Cycles
Реализация Python на C использует подсчёт ссылок для реализации сборки мусора. Каждый объект Python хранит счётчик количества ссылок, указывающих на него, и обновляет этот счётчик при создании или удалении ссылок. Когда счётчик ссылок достигает нуля, объект становится недоступным, поскольку для доступа к объекту необходима ссылка на него, а если счётчик равен нулю, ссылок больше не существует.
Подсчёт ссылок имеет ряд приятных свойств: его легко понять и реализовать, а результирующая реализация является переносимой, достаточно быстрой и хорошо взаимодействует с другими библиотеками, реализующими собственные схемы управления памятью. Основная проблема подсчёта ссылок заключается в том, что он иногда не замечает, что объекты стали недоступными, что приводит к утечке памяти. Это происходит при наличии циклических ссылок.
Рассмотрим простейший возможный цикл – экземпляр класса, который содержит ссылку на самого себя:
instance = SomeClass()
instance.myself = instance
После выполнения двух приведённых выше строк кода счётчик ссылок instance равен 2: одна ссылка – от переменной с именем 'instance', а другая – от атрибута myself экземпляра.
Если следующая строка кода – del instance, что произойдёт? Счётчик ссылок instance уменьшается на 1, поэтому он становится равен 1; ссылка в атрибуте myself всё ещё существует. Однако экземпляр больше недоступен из кода Python и может быть удалён. Несколько объектов могут образовывать цикл, если они ссылаются друг на друга, что приводит к утечке всех этих объектов.
Python 2.0 решает эту проблему, периодически запуская алгоритм обнаружения циклов, который ищет недоступные циклы и удаляет задействованные объекты. Новый модуль gc предоставляет функции для выполнения сборки мусора, получения отладочной статистики и настройки параметров сборщика.
Запуск алгоритма обнаружения циклов требует времени и, следовательно, приводит к дополнительным накладным расходам. Предполагается, что после получения опыта работы со сборкой циклов в версии 2.0, в Python 2.1 удастся минимизировать эти накладные расходы за счёт тщательной настройки. Пока не ясно, насколько падает производительность, потому что измерять это сложно и сильно зависит от того, как часто программа создаёт и уничтожает объекты. Обнаружение циклов можно отключить при компиляции Python, если недопустимо даже малейшее снижение скорости или есть подозрения, что сборка циклов работает некорректно, указав ключ --without-cycle-gc при запуске сценария configure.
Несколько человек взялись за эту проблему и внесли свой вклад в решение. Ранняя реализация подхода с обнаружением циклов была написана Тоби Келси. Текущий алгоритм предложил Эрик Тидерманн во время визита в CNRI, а Гвидо ван Россум и Нил Шеменауэр написали две разные реализации, которые позже были объединены Нилом. Многие другие люди высказывали предложения по ходу дела; в архивах марта 2000 года списка рассылки python-dev содержится большая часть соответствующих обсуждений, особенно в темах «Reference cycle collection for Python» и «Finalization again».
Другие основные изменения¶Other Core Changes
В синтаксис и встроенные функции Python был внесён ряд небольших изменений. Ни одно из них не является очень масштабным, но все они представляют собой удобные возможности.
Небольшие изменения языка¶Minor Language Changes
Новый синтаксис упрощает вызов заданной функции с кортежем аргументов и/или словарём именованных аргументов. В Python 1.5 и более ранних версиях использовалась встроенная функция apply(): apply(f, args, kw) вызывает функцию f() с кортежем аргументов args и именованными аргументами из словаря kw. В Python 2.0 apply() делает то же самое, но благодаря патчу от Грега Юинга f(*args, **kw) предоставляет более короткий и понятный способ достижения того же эффекта. Этот синтаксис симметричен синтаксису определения функций:
def f(*args, **kw):
# args – это кортеж позиционных аргументов,
# kw – это словарь именованных аргументов
...
Теперь оператор print может направлять свой вывод в объект, подобный файлу, если после print указать >> file, как оператор перенаправления в оболочках Unix. Раньше приходилось либо использовать метод write() файлоподобного объекта, что лишено удобства и простоты print, либо присваивать новое значение sys.stdout, а затем восстанавливать старое. Для вывода в стандартный поток ошибок гораздо проще написать:
print >> sys.stderr, "Warning: action field not supplied"
Теперь модули можно переименовывать при импорте, используя синтаксис import module
as name или from module import name as othername. Патч был представлен Томасом Воутерсом.
При использовании оператора % стал доступен новый стиль форматирования: ‘%r’ вставляет repr() своего аргумента. Это было добавлено из соображений симметрии, на этот раз с существующим стилем ‘%s’, который вставляет str() аргумента. Например, '%r %s' % ('abc',
'abc') возвращает строку, содержащую 'abc' abc.
Раньше не было возможности реализовать класс, переопределяющий встроенный оператор Python in и предоставляющий собственную версию. obj in seq возвращает true, если obj присутствует в последовательности seq; Python вычисляет это, просто перебирая все индексы последовательности, пока не найдёт obj или не встретит исключение IndexError. Моше Задка внёс патч, добавляющий магический метод __contains__() для обеспечения пользовательской реализации in. Кроме того, новые встроенные объекты, написанные на C, могут определять, что для них означает in, через новый слот в протоколе последовательностей.
Более ранние версии Python использовали рекурсивный алгоритм для удаления объектов. Глубоко вложенные структуры данных могли привести к переполнению C-стека интерпретатора и аварийному завершению; Кристиан Тисмер переписал логику удаления, чтобы исправить эту проблему. Похожим образом, сравнение рекурсивных объектов приводило к бесконечной рекурсии и краху; Джереми Хилтон переписал код так, чтобы он больше не падал, а выдавал полезный результат. Например, после этого кода:
a = []
b = []
a.append(a)
b.append(b)
Сравнение a==b возвращает true, потому что две рекурсивные структуры данных изоморфны. См. тему «trashcan and PR#7» в архивах апреля 2000 года списка рассылки python-dev для обсуждения, предшествовавшего этой реализации, а также некоторые полезные ссылки. Обратите внимание, что теперь сравнения также могут вызывать исключения. В более ранних версиях Python операция сравнения, например cmp(a,b), всегда давала ответ, даже если пользовательский метод __cmp__() сталкивался с ошибкой, поскольку возникшее исключение просто молча проглатывалось.
Проводилась работа по портированию Python на 64-разрядную Windows для процессора Itanium, в основном силами Трента Мика из ActiveState. (Сбивает с толку, что sys.platform по-прежнему 'win32' на Win64, поскольку, как кажется, для облегчения портирования MS Visual C++ обрабатывает код как 32-разрядный на Itanium.) PythonWin также поддерживает Windows CE; дополнительную информацию можно найти на странице Python CE по адресу http://pythonce.sourceforge.net/.
Ещё одна новая платформа – Darwin/MacOS X; начальная поддержка для неё появилась в Python 2.0. Динамическая загрузка работает, если указать «configure –with-dyld –with-suffix=.x». За дополнительными инструкциями обращайтесь к файлу README в дистрибутиве исходного кода Python.
Была предпринята попытка смягчить один из недостатков Python – часто сбивающее с толку исключение NameError, когда код обращается к локальной переменной до того, как ей присвоено значение. Например, следующий код вызывает исключение в операторе print как в версии 1.5.2, так и в 2.0; в 1.5.2 возбуждается NameError, а в 2.0 – новое исключение UnboundLocalError. UnboundLocalError является подклассом NameError, поэтому любой существующий код, ожидающий NameError, по-прежнему должен работать.
def f():
print "i=",i
i = i + 1
f()
Были введены два новых исключения: TabError и IndentationError. Оба являются подклассами SyntaxError и возбуждаются, когда код Python имеет неправильный отступ.
Изменения во встроенных функциях¶Changes to Built-in Functions
Была добавлена новая встроенная функция zip(seq1, seq2, ...). zip() возвращает список кортежей, где каждый кортеж содержит i-й элемент из каждой из последовательностей-аргументов. Разница между zip() и map(None,
seq1, seq2) в том, что map() дополняет последовательности значением None, если они не одинаковой длины, а zip() усекает возвращаемый список до длины самой короткой последовательности.
Функции int() и long() теперь принимают необязательный параметр «base», когда первый аргумент является строкой. int('123', 10) возвращает 123, а int('123', 16) возвращает 291. int(123, 16) вызывает исключение TypeError с сообщением «can’t convert non-string with explicit base».
В модуль sys была добавлена новая переменная, содержащая более подробную информацию о версии. sys.version_info – это кортеж (major, minor, micro,
level, serial). Например, в гипотетической версии 2.0.1beta1, sys.version_info будет равно (2, 0, 1, 'beta', 1). level – строка, такая как "alpha", "beta" или "final" для финального релиза.
У словарей появился необычный новый метод setdefault(key, default), который ведёт себя аналогично существующему методу get(). Однако, если ключ отсутствует, setdefault() одновременно возвращает значение default, как это сделал бы get(), и вставляет его в словарь как значение для key. Таким образом, следующие строки кода:
if dict.has_key( key ): return dict[key]
else:
dict[key] = []
return dict[key]
можно заменить одним оператором return dict.setdefault(key, []).
Интерпретатор устанавливает максимальную глубину рекурсии, чтобы отлавливать неконтролируемую рекурсию до переполнения C-стека и сбоя с дампом памяти или GPF. Раньше этот предел был фиксирован при компиляции Python, но в версии 2.0 максимальную глубину рекурсии можно прочитать и изменить с помощью sys.getrecursionlimit() и sys.setrecursionlimit(). Значение по умолчанию – 1000, а примерное максимальное значение для данной платформы можно узнать, запустив новый сценарий Misc/find_recursionlimit.py.
Переход на версию 2.0¶Porting to 2.0
Новые релизы Python стараются быть совместимыми с предыдущими, и до сих пор это удавалось довольно хорошо. Однако некоторые изменения считаются достаточно полезными, обычно потому что они исправляют изначальные проектные решения, оказавшиеся ошибочными, и нарушения обратной совместимости не всегда можно избежать. В этом разделе перечислены изменения в Python 2.0, которые могут привести к неработоспособности старого кода.
Изменение, которое, вероятно, сломает больше всего кода, – это ужесточение требований к аргументам, принимаемым некоторыми методами. Некоторые методы принимали несколько аргументов и обрабатывали их как кортеж, в частности различные методы списков, такие как append() и insert(). В более ранних версиях Python, если L – это список, вызов L.append( 1,2 ) добавляет кортеж (1,2) в список. В Python 2.0 это вызывает исключение TypeError с сообщением: «append требует ровно 1 аргумент; получено 2». Исправление просто: добавить дополнительные скобки, чтобы передать оба значения как кортеж: L.append( (1,2) ).
Более ранние версии этих методов были более снисходительными, поскольку они использовали старую функцию в C-интерфейсе Python для разбора аргументов; версия 2.0 модернизирует их, используя PyArg_ParseTuple() – текущую функцию разбора аргументов, которая выдаёт более полезные сообщения об ошибках и рассматривает вызовы с несколькими аргументами как ошибки. Если вы абсолютно обязаны использовать 2.0, но не можете исправить свой код, вы можете отредактировать Objects/listobject.c и определить символ препроцессора NO_STRICT_LIST_APPEND, чтобы сохранить старое поведение; это не рекомендуется.
Некоторые функции в модуле socket все еще снисходительны в этом отношении. Например, socket.connect( ('hostname', 25) )() – это правильная форма, передающая кортеж, представляющий IP-адрес, но socket.connect(
'hostname', 25 )() также работает. socket.connect_ex() и socket.bind() аналогично терпимы. Версия 2.0alpha1 ужесточила эти функции, но из-за того, что документация на самом деле использовала ошибочную форму с несколькими аргументами, многие люди написали код, который сломался бы при более строгой проверке. GvR отменил изменения под давлением общественности, поэтому для модуля socket документация была исправлена, а форма с несколькими аргументами просто помечена как устаревшая; она будет снова ужесточена в будущей версии Python.
Экранирование \x в строковых литералах теперь принимает ровно 2 шестнадцатеричные цифры. Ранее оно потребляло все следующие за 'x' шестнадцатеричные цифры и брало младшие 8 бит результата, поэтому \x123456 было эквивалентно \x56.
Исключения AttributeError и NameError теперь имеют более понятное сообщение об ошибке, текст которого будет примерно таким: 'Spam' instance has no
attribute 'eggs' или name 'eggs' is not defined. Ранее сообщение об ошибке содержало только имя отсутствующего атрибута eggs, и код, написанный с учётом этого, сломается в версии 2.0.
Была проделана работа, чтобы сделать целые числа и длинные целые числа более взаимозаменяемыми. В версии 1.5.2 была добавлена поддержка больших файлов для Solaris, позволяющая читать файлы размером более 2 ГБ; это заставило метод tell() файловых объектов возвращать длинное целое вместо обычного. Некоторый код вычитал два смещения файла и пытался использовать результат для умножения последовательности или извлечения среза строки, но это вызывало TypeError. В версии 2.0 длинные целые можно использовать для умножения или извлечения среза последовательности, и это будет работать так, как интуитивно ожидается; 3L * 'abc' даёт 'abcabcabc', а (0,1,2,3)[2L:4L] даёт (2,3). Длинные целые также можно использовать в различных контекстах, где раньше принимались только обычные целые, например, в методе seek() файловых объектов и в форматах, поддерживаемых оператором % (%d, %i, %x и т.д.). Например, "%d" % 2L**64 даст строку 18446744073709551616.
Самое тонкое изменение длинных целых заключается в том, что str() длинного целого больше не содержит завершающего символа 'L', хотя repr() всё ещё включает его. Символ 'L' раздражал многих, кто хотел печатать длинные целые, чтобы они выглядели как обычные целые, поскольку им приходилось специально удалять этот символ. В версии 2.0 это больше не проблема, но код, который делает str(longval)[:-1] и предполагает наличие 'L', теперь потеряет последнюю цифру.
Преобразование числа с плавающей точкой с помощью repr() теперь использует другую точность форматирования, чем str(). repr() использует строку формата %.17g для C-функции sprintf(), тогда как str() использует %.12g как и раньше. В результате repr() может иногда показывать больше десятичных знаков, чем str() для некоторых чисел. Например, число 8.1 не может быть точно представлено в двоичном виде, поэтому repr(8.1) равно '8.0999999999999996', а str(8.1) равно '8.1'.
Опция командной строки -X, которая превращала все стандартные исключения в строки вместо классов, была удалена; стандартные исключения теперь всегда будут классами. Модуль exceptions, содержащий стандартные исключения, был переведён с Python на встроенный модуль на C, написанный Барри Уорсо и Фредриком Лундом.
Изменения в расширении и встраивании¶Extending/Embedding Changes
Некоторые изменения находятся «под капотом» и будут заметны только тем, кто пишет модули расширения на C или встраивает интерпретатор Python в более крупное приложение. Если вы не работаете с C API Python, можете смело пропустить этот раздел.
Номер версии Python C API был увеличен, поэтому расширения на C, скомпилированные для версии 1.5.2, должны быть перекомпилированы для работы с версией 2.0. В Windows из-за особенностей работы DLL Python 2.0 не может импортировать сторонние расширения, собранные для Python 1.5.x; Python вызовет исключение, и импорт не удастся.
Пользователи модуля ExtensionClass Джима Фултона будут рады узнать, что были добавлены хуки, благодаря которым ExtensionClasses теперь поддерживаются в isinstance() и issubclass(). Это означает, что больше не нужно помнить о написании кода вроде if type(obj) == myExtensionClass, а можно использовать более естественную форму if isinstance(obj, myExtensionClass).
Файл Python/importdl.c, который представлял собой массу #ifdef'ов для поддержки динамической загрузки на многих различных платформах, был очищен и реорганизован Грегом Стейном. importdl.c теперь довольно мал, а платформозависимый код был перемещён в набор файлов Python/dynload_*.c. Ещё одна чистка: в каталоге Include/ также было несколько файлов my*.h, содержащих различные переносимые уловки; они были объединены в один файл Include/pyport.h.
Долгожданная реструктуризация malloc от Владимира Марангозова была завершена; теперь легко сделать так, чтобы интерпретатор Python использовал пользовательский распределитель вместо стандартного malloc() языка C. Документацию можно найти в комментариях к Include/pymem.h и Include/objimpl.h. За продолжительными обсуждениями, в ходе которых был выработан интерфейс, можно обратиться к веб-архивам списков рассылки «patches» и «python-dev» на python.org.
Последние версии среды разработки GUSI для MacOS поддерживают POSIX-потоки. Поэтому поддержка POSIX-потоков в Python теперь работает на Macintosh. Также была предоставлена поддержка потоков с использованием библиотеки GNU pth пользовательского пространства.
Поддержка потоков в Windows также была улучшена. Windows поддерживает блокировки потоков, которые используют объекты ядра только в случае конкуренции; в типичном случае, когда конкуренции нет, используются более простые функции, которые на порядок быстрее. Потоковая версия Python 1.5.2 на NT работает в два раза медленнее однопоточной; с изменениями в 2.0 разница составляет всего 10%. Эти улучшения были внесены Яковом Марковичем.
Исходный код Python 2.0 теперь использует только прототипы ANSI C, поэтому для компиляции Python требуется компилятор ANSI C, и больше нельзя использовать компилятор, поддерживающий только K&R C.
Ранее виртуальная машина Python использовала 16-битные числа в своём байт-коде, что ограничивало размер исходных файлов. В частности, это влияло на максимальный размер литеральных списков и словарей в исходном коде Python; время от времени разработчики, генерирующие код Python, сталкивались с этим ограничением. Патч Чарльза Дж. Уолдмана поднимает предел с 2^16 до 2^{32}.
Были добавлены три новые удобные функции для добавления констант в словарь модуля во время его инициализации: PyModule_AddObject(), PyModule_AddIntConstant() и PyModule_AddStringConstant(). Каждая из этих функций принимает объект модуля, заканчивающуюся нулевым символом строку C, содержащую имя добавляемой константы, и третий аргумент – значение, которое будет присвоено этому имени. Этот третий аргумент – соответственно объект Python, значение типа long в C или строка C.
Был добавлен API-обёртка для обработчиков сигналов в стиле Unix. PyOS_getsig() получает обработчик сигнала, а PyOS_setsig() устанавливает новый обработчик.
Distutils: упрощение установки модулей¶Distutils: Making Modules Easy to Install
До Python 2.0 установка модулей была утомительным делом – не было возможности автоматически определить, где установлен Python, или какие параметры компилятора использовать для модулей расширения. Авторам программного обеспечения приходилось проходить через утомительный ритуал редактирования файлов Makefile и конфигурационных файлов, который нормально работал только на Unix и не поддерживал Windows и MacOS. Пользователи Python сталкивались с сильно различающимися инструкциями по установке для разных пакетов расширений, что делало администрирование установки Python довольно обременительным.
SIG (специальная группа интересов) по утилитам распространения, возглавляемая Грегом Уордом, создала Distutils – систему, значительно упрощающую установку пакетов. Они образуют пакет distutils, новую часть стандартной библиотеки Python. В лучшем случае установка модуля Python из исходного кода будет состоять из тех же шагов: сначала нужно просто распаковать tarball или zip-архив, а затем выполнить «python
setup.py install». Платформа будет автоматически определена, компилятор распознан, модули расширения на C скомпилированы, а дистрибутив установлен в соответствующий каталог. Необязательные аргументы командной строки обеспечивают больший контроль над процессом установки; пакет distutils предоставляет множество мест для переопределения значений по умолчанию – разделение сборки и установки, сборка или установка в нестандартные каталоги и многое другое.
Для использования Distutils необходимо написать сценарий setup.py. В простом случае, когда программное обеспечение содержит только .py файлы, минимальный setup.py может состоять всего из нескольких строк:
from distutils.core import setup
setup (name = "foo", version = "1.0",
py_modules = ["module1", "module2"])
Файл setup.py ненамного сложнее, если программное обеспечение состоит из нескольких пакетов:
from distutils.core import setup
setup (name = "foo", version = "1.0",
packages = ["package", "package.subpackage"])
Расширение на C может быть самым сложным случаем; вот пример, взятый из пакета PyXML:
from distutils.core import setup, Extension
expat_extension = Extension('xml.parsers.pyexpat',
define_macros = [('XML_NS', None)],
include_dirs = [ 'extensions/expat/xmltok',
'extensions/expat/xmlparse' ],
sources = [ 'extensions/pyexpat.c',
'extensions/expat/xmltok/xmltok.c',
'extensions/expat/xmltok/xmlrole.c', ]
)
setup (name = "PyXML", version = "0.5.4",
ext_modules =[ expat_extension ] )
Distutils также может заботиться о создании исходных и бинарных дистрибутивов. Команда «sdist», запускаемая через «python setup.py sdist», создаёт исходный дистрибутив, например foo-1.0.tar.gz. Добавление новых команд несложно; команды «bdist_rpm» и «bdist_wininst» уже были предоставлены для создания RPM-дистрибутива и установщика для Windows соответственно. Команды для создания других форматов дистрибутивов, таких как пакеты Debian и файлы .pkg для Solaris, находятся на разных стадиях разработки.
Всё это описано в новом руководстве Distributing Python Modules, которое пополняет основной набор документации Python.
Модули XML¶XML Modules
Python 1.5.2 включал простой XML-парсер в виде модуля xmllib, предоставленного Сурдом Мюллендером. С момента выхода 1.5.2 стали распространены два различных интерфейса для обработки XML: SAX2 (версия 2 простого API для XML), предоставляющий событийно-ориентированный интерфейс с некоторыми сходствами с xmllib, и DOM (объектная модель документа), предоставляющий древовидный интерфейс, преобразующий XML-документ в дерево узлов, которое можно обходить и модифицировать. Python 2.0 включает интерфейс SAX2 и урезанный интерфейс DOM в составе пакета xml. Здесь мы дадим краткий обзор этих новых интерфейсов; полные подробности можно найти в документации Python или в исходном коде. Python XML SIG также работает над улучшенной документацией.
Поддержка SAX2¶SAX2 Support
SAX определяет событийно-ориентированный интерфейс для разбора XML. Для использования SAX необходимо написать класс-обработчик SAX. Классы-обработчики наследуются от различных классов, предоставляемых SAX, и переопределяют различные методы, которые затем будут вызываться XML-парсером. Например, методы startElement() и endElement() вызываются для каждого открывающего и закрывающего тега, встреченного парсером; метод characters() вызывается для каждого фрагмента символьных данных и так далее.
Преимущество событийно-ориентированного подхода в том, что весь документ не должен постоянно находиться в памяти, что важно при обработке действительно огромных документов. Однако написание класса-обработчика SAX может сильно усложниться, если вы пытаетесь модифицировать структуру документа каким-либо сложным образом.
Например, эта небольшая программа определяет обработчик, который печатает сообщение для каждого открывающего и закрывающего тега, а затем анализирует файл hamlet.xml, используя его:
from xml import sax
class SimpleHandler(sax.ContentHandler):
def startElement(self, name, attrs):
print 'Start of element:', name, attrs.keys()
def endElement(self, name):
print 'End of element:', name
# Создать объект парсера
parser = sax.make_parser()
# Указать ему, какой обработчик использовать
handler = SimpleHandler()
parser.setContentHandler( handler )
# Разобрать файл!
parser.parse( 'hamlet.xml' )
За дополнительной информацией обращайтесь к документации Python или XML HOWTO по адресу http://pyxml.sourceforge.net/topics/howto/xml-howto.html.
Поддержка DOM¶DOM Support
Document Object Model (DOM) – это древовидное представление XML-документа. Экземпляр верхнего уровня Document является корнем дерева и имеет единственный дочерний элемент – экземпляр верхнего уровня Element. Этот Element содержит дочерние узлы, представляющие символьные данные и любые вложенные элементы, которые, в свою очередь, могут иметь собственные дочерние узлы, и так далее. Используя DOM, можно обходить полученное дерево любым способом, получать значения элементов и атрибутов, вставлять и удалять узлы, а также преобразовывать дерево обратно в XML.
DOM удобен для изменения XML-документов, поскольку можно создать DOM-дерево, изменить его, добавляя новые узлы или перестраивая поддеревья, а затем получить на выходе новый XML-документ. Также можно вручную построить DOM-дерево и преобразовать его в XML – это может быть более гибким способом создания XML-вывода, чем простая запись <tag1>…</tag1> в файл.
Реализация DOM, включённая в Python, находится в модуле xml.dom.minidom. Это облегчённая реализация DOM уровня 1 с поддержкой пространств имён XML. Для построения DOM-дерева предоставляются вспомогательные функции parse() и parseString():
from xml.dom import minidom
doc = minidom.parse('hamlet.xml')
doc является экземпляром Document. Document, как и все остальные классы DOM, такие как Element и Text, является подклассом базового класса Node. Таким образом, все узлы DOM-дерева поддерживают определённые общие методы, например toxml(), который возвращает строку, содержащую XML-представление узла и его дочерних элементов. Каждый класс также имеет собственные специальные методы; например, экземпляры Element и Document имеют метод для поиска всех дочерних элементов с заданным именем тега. Продолжая предыдущий пример из двух строк:
perslist = doc.getElementsByTagName( 'PERSONA' )
print perslist[0].toxml()
print perslist[1].toxml()
Для XML-файла Hamlet несколько строк выше выводят:
<PERSONA>CLAUDIUS, king of Denmark. </PERSONA>
<PERSONA>HAMLET, son to the late, and nephew to the present king.</PERSONA>
Корневой элемент документа доступен как doc.documentElement, а его дочерние элементы можно легко изменить, удаляя, добавляя или убирая узлы:
root = doc.documentElement
# Удалить первый дочерний элемент
root.removeChild( root.childNodes[0] )
# Переместить новый первый дочерний элемент в конец
root.appendChild( root.childNodes[0] )
# Вставить новый первый дочерний элемент (изначально
# третий дочерний элемент) перед 20-м дочерним элементом.
root.insertBefore( root.childNodes[0], root.childNodes[20] )
Опять же, я отсылаю вас к документации Python для получения полного списка различных классов Node и их методов.
Отношение к PyXML¶Relationship to PyXML
Специальная группа по XML (XML Special Interest Group) уже некоторое время работает над кодом Python, связанным с XML. Её дистрибутив кода под названием PyXML доступен на веб-страницах группы по адресу https://www.python.org/community/sigs/current/xml-sig. Дистрибутив PyXML также использовал имя пакета xml. Если вы писали программы с использованием PyXML, вас наверняка интересует его совместимость с пакетом xml версии 2.0.
Ответ заключается в том, что пакет xml в Python 2.0 несовместим с PyXML, но его можно сделать совместимым, установив свежую версию PyXML. Многие приложения могут обойтись поддержкой XML, входящей в Python 2.0, но более сложным приложениям потребуется установка полного пакета PyXML. После установки PyXML версии 0.6.0 или новее заменит пакет xml, поставляемый с Python, и будет строгим надмножеством стандартного пакета, добавляя множество дополнительных возможностей. Некоторые из дополнительных функций PyXML включают:
4DOM – полная реализация DOM от FourThought, Inc.
Валидирующий парсер xmlproc, написанный Ларсом Мариусом Гаршолем.
Модуль ускорения парсера
sgmlop, написанный Фредриком Лундом.
Изменения в модулях¶Module changes
В обширную стандартную библиотеку Python было внесено множество улучшений и исправлений; некоторые из затронутых модулей включают readline, ConfigParser, cgi, calendar, posix, readline, xmllib, aifc, chunk, wave, random, shelve и nntplib. Обратитесь к журналам CVS для получения точных подробностей по каждому патчу.
Брайан Галлью добавил поддержку OpenSSL для модуля socket. OpenSSL – это реализация протокола Secure Socket Layer, который шифрует данные, передаваемые через сокет. При компиляции Python можно отредактировать Modules/Setup, чтобы включить поддержку SSL, что добавляет дополнительную функцию в модуль socket: socket.ssl(socket, keyfile, certfile), которая принимает объект сокета и возвращает SSL-сокет. Модули httplib и urllib также были изменены для поддержки URL-адресов https://, хотя никто не реализовал FTP или SMTP поверх SSL.
Модуль httplib был переписан Грегом Штейном для поддержки HTTP/1.1. Обеспечена обратная совместимость с версией 1.5 модуля httplib, хотя использование таких возможностей HTTP/1.1, как конвейеризация, потребует переписывания кода для использования другого набора интерфейсов.
Модуль Tkinter теперь поддерживает Tcl/Tk версий 8.1, 8.2 или 8.3, а поддержка старых версий 7.x прекращена. Модуль Tkinter теперь поддерживает отображение строк Unicode в виджетах Tk. Кроме того, Фредрик Лунд предложил оптимизацию, которая делает операции вроде create_line и create_polygon значительно быстрее, особенно при использовании большого количества координат.
Модуль curses был значительно расширен, начиная с улучшенной версии Оливера Андриха, чтобы предоставить множество дополнительных функций из ncurses и SYSV curses, таких как цвета, поддержка альтернативных наборов символов, pad'ы и поддержка мыши. Это означает, что модуль больше не совместим с операционными системами, имеющими только BSD curses, но, похоже, в настоящее время нет поддерживаемых ОС, попадающих в эту категорию.
Как упоминалось ранее при обсуждении поддержки Unicode в версии 2.0, базовая реализация регулярных выражений, предоставляемая модулем re, была изменена. SRE – новый движок регулярных выражений, написанный Фредриком Лундом и частично финансируемый Hewlett Packard, поддерживает сопоставление как с 8-битными строками, так и со строками Unicode.
Новые модули¶New modules
Было добавлено несколько новых модулей. Мы просто перечислим их с краткими описаниями; за подробностями о конкретном модуле обращайтесь к документации версии 2.0.
atexit: Для регистрации функций, вызываемых перед завершением интерпретатора Python. Код, который в настоящее время устанавливаетsys.exitfuncнапрямую, следует изменить для использования модуляatexitвместо этого, импортируяatexitи вызываяatexit.register()с функцией, которая должна быть вызвана при завершении. (Предложено Скипом Монтанаро.)codecs,encodings,unicodedata: Добавлены в рамках новой поддержки Unicode.filecmp: Заменяет старые модулиcmp,cmpcacheиdircmp, которые теперь считаются устаревшими. (Предложено Гордоном МакМилланом и Моше Задкой.)gettext: Этот модуль обеспечивает поддержку интернационализации (I18N) и локализации (L10N) для программ Python, предоставляя интерфейс к библиотеке каталогов сообщений GNU gettext. (Интегрирован Барри Варшавой на основе отдельных вкладов Мартина фон Лёвиса, Питера Фанка и Джеймса Хенстриджа.)linuxaudiodev: Поддержка устройства/dev/audioв Linux, аналог существующего модуляsunaudiodev. (Предложено Питером Бошем, исправления Джереми Хилтона.)mmap: Интерфейс к файлам, отображаемым в память, как в Windows, так и в Unix. Содержимое файла может быть отображено непосредственно в память, после чего оно ведёт себя как изменяемая строка, поэтому его можно читать и изменять. Их даже можно передавать функциям, ожидающим обычные строки, например модулюre. (Предложено Сэмом Рашингом, с некоторыми расширениями от А.М. Кухлинга.)pyexpat: Интерфейс к XML-парсеру Expat. (Предложено Полом Прескодом.)robotparser: Разбирает файлrobots.txt, который используется для написания веб-пауков, вежливо избегающих определённых областей веб-сайта. Анализатор принимает содержимое файлаrobots.txt, строит из него набор правил и затем может отвечать на вопросы о возможности загрузки заданного URL. (Предложено Скипом Монтанаро.)tabnanny: Модуль/скрипт для проверки неоднозначных отступов в исходном коде Python. (Внёс Тим Питерс.)UserString: Базовый класс для создания объектов, ведущих себя как строки.webbrowser: Модуль, предоставляющий платформонезависимый способ запуска веб-браузера по определённому URL. Для каждой платформы перебираются различные браузеры в определённом порядке. Пользователь может изменить, какой браузер запускается, задав переменную окружения BROWSER. (Изначально вдохновлён патчем Эрика С. Реймонда кurllib, который добавлял похожую функциональность, но итоговый модуль происходит из кода, первоначально реализованного Фредом Дрейком какTools/idle/BrowserControl.pyи адаптированного для стандартной библиотеки Фредом.)_winreg: Интерфейс к реестру Windows._winreg– это адаптация функций, входящих в PythonWin с 1995 года, но теперь добавленная в основную поставку и расширенная для поддержки Unicode._winregнаписан Биллом Таттом и Марком Хаммондом.zipfile: Модуль для чтения и записи архивов в формате ZIP. Это архивы, созданные PKZIP на DOS/Windows или zip на Unix, не путать с файлами формата gzip (которые поддерживаются модулемgzip) (Внёс Джеймс К. Альстрём.)imputil: Модуль, предоставляющий более простой способ написания пользовательских хуков импорта по сравнению с существующим модулемihooks. (Реализован Грегом Стейном, при активном обсуждении в python-dev.)
Улучшения IDLE¶IDLE Improvements
IDLE – официальная кроссплатформенная среда разработки Python, написанная с использованием Tkinter. Python 2.0 включает IDLE 0.6, в котором добавлен ряд новых возможностей и улучшений. Частичный список:
Улучшения и оптимизации интерфейса, особенно в области подсветки синтаксиса и автоматических отступов.
Браузер классов теперь показывает больше информации, например, функции верхнего уровня в модуле.
Ширина табуляции теперь настраивается пользователем. При открытии существующего файла Python IDLE автоматически определяет соглашения об отступах и адаптируется.
Теперь поддерживается вызов браузеров на различных платформах для открытия документации Python в браузере.
IDLE теперь имеет командную строку, в значительной степени подобную стандартному интерпретатору Python.
Подсказки вызова (call tips) добавлены во многих местах.
IDLE теперь можно установить как пакет.
В окне редактора теперь внизу отображается строка/столбец.
Три новые команды клавиш: Проверить модуль (Alt-F5), Импортировать модуль (F5) и Выполнить скрипт (Ctrl-F5).
Удалённые и устаревшие модули¶Deleted and Deprecated Modules
Несколько модулей были удалены, потому что они устарели или появились более
лучшие способы делать то же самое. Модуль stdwin исчез; он был предназначен для
платформонезависимого оконного инструментария, который больше не развивается.
Ряд модулей был перенесён в подкаталог lib-old:
cmp, cmpcache, dircmp, dump, find,
grep, packmail, poly, util, whatsound,
zmod. Если у вас есть код, зависящий от модуля, перенесённого в
lib-old, вы можете просто добавить этот каталог в sys.path, чтобы
вернуть их, но рекомендуется обновить любой код, использующий эти модули.
Благодарности¶Acknowledgements
Авторы хотели бы поблагодарить следующих людей за предложения по различным черновикам этой статьи: Дэвид Болен, Марк Хаммонд, Грегг Хаузер, Джереми Хилтон, Фредрик Лунд, Детлеф Ланнерт, Ааз Марук, Скип Монтанаро, Владимир Марангозов, Тобиас Полцин, Гвидо ван Россум, Нил Шеменауэр и Расс Шмидт.