# Що нового в Python 2.0

Автор:

  A.M. Kuchling та Moshe Zadka

## вступ

Новий випуск Python, версія 2.0, був випущений 16 жовтня 2000 року. У цій статті розглядаються цікаві нові можливості версії 2.0, висвітлюються деякі інші корисні зміни та вказується на кілька несумісних змін, які можуть вимагати переписування коду.

Python’s development never completely stops between releases, and a steady flow of bug fixes and improvements are always being submitted. A host of minor fixes, a few optimizations, additional docstrings, and better error messages went into 2.0; to list them all would be impossible, but they’re certainly significant. Consult the publicly available CVS logs if you want to see the full list. This progress is due to the five developers working for PythonLabs are now getting paid to spend their days fixing bugs, and also due to the improved communication resulting from moving to SourceForge.

## Що щодо Python 1.6?

Python 1.6 можна вважати випуском Python Contractual Obligations. Після того, як основна команда розробників залишила 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, оскільки з травня по вересень було виконано багато роботи.

## Новий процес розвитку

Найважливіша зміна в Python 2.0 може стосуватися зовсім не коду, а способу розробки Python: у травні 2000 року розробники Python почали використовувати інструменти, надані SourceForge для зберігання вихідного коду, відстеження звітів про помилки та керування чергою. подання патчів. Щоб повідомити про помилки або надіслати виправлення для Python 2.0, використовуйте інструменти відстеження помилок і керування виправленнями, доступні на сторінці проекту Python, розташованій за адресою https://sourceforge.net/projects/python/.

Найважливішою з послуг, які зараз розміщені на SourceForge, є дерево Python CVS, репозиторій з контрольованими версіями, що містить вихідний код для Python. Раніше було приблизно 7 або близько того людей, які мали доступ для запису до дерева CVS, і всі латки повинні були бути перевірені та зареєстровані одним із людей у цьому короткому списку. Очевидно, що це було не дуже масштабовано. Завдяки переміщенню дерева CVS до SourceForge стало можливим надати доступ для запису більшій кількості людей; станом на вересень 2000 року було 27 осіб, які могли перевірити зміни, тобто чотириразове збільшення. Це робить можливими масштабні зміни, які б не були зроблені, якби їх довелося фільтрувати через невелику групу основних розробників. Наприклад, одного разу Пітер Шнайдер-Камп спав на думку відмовитися від сумісності з K&R C і перетворити вихідний код C для Python на ANSI C. Отримавши схвалення в списку розсилки python-dev, він розпочав шквал перевірок, які тривали близько тижня інші розробники приєдналися, щоб допомогти, і роботу було виконано. Якби було лише 5 осіб із доступом для запису, ймовірно, це завдання було б сприйняте як «гарне, але не варте потрібного часу та зусиль», і воно ніколи не було б виконане.

Перехід до використання послуг SourceForge призвів до значного збільшення швидкості розробки. Патчі тепер надсилаються, коментуються, переглядаються людьми, які не були початковим відправником, і обмінюються між людьми, доки виправлення не буде визнано вартим перевірки. Помилки відстежуються в одному центральному місці та можуть бути призначені конкретній особі для виправлення , і ми можемо підрахувати кількість відкритих помилок для вимірювання прогресу. Це не обійшлося без витрат: розробники тепер мають більше електронної пошти, щоб мати справу з більшою кількістю списків розсилки, і для нового середовища потрібно було написати спеціальні інструменти. Наприклад, SourceForge надсилає повідомлення електронною поштою про стандартні виправлення та сповіщення про помилки, які абсолютно марні, тому Ka-Ping Yee написав HTML-скрейпер, який надсилає більш корисні повідомлення.

Легкість додавання коду спричинила кілька початкових труднощів, наприклад код перевірявся до того, як він був готовий, або без отримання чіткої згоди від групи розробників. Процес затвердження, який з’явився, дещо схожий на той, який використовується групою Apache. Розробники можуть голосувати за патч +1, +0, -0 або -1; +1 і -1 означають прийняття або відхилення, тоді як +0 і -0 означають, що розробник здебільшого байдужий до змін, хоча з невеликим позитивним або негативним ухилом. Найсуттєвішою зміною в порівнянні з моделлю Apache є те, що голосування є, по суті, дорадчим, дозволяючи Гвідо ван Россуму, який має статус доброзичливого довічного диктатора, знати, якою є загальна думка. Він все ще може ігнорувати результати голосування та схвалити або відхилити зміни, навіть якщо спільнота з ним не погоджується.

Створення фактичного патча є останнім кроком у додаванні нової функції, і зазвичай це легко порівняно з попереднім завданням створення гарного дизайну. Обговорення нових функцій часто може вибухнути в довгі ланцюжки списків розсилки, що ускладнює стеження за обговоренням, і ніхто не може прочитати кожну публікацію на python-dev. Тому було створено відносно формальний процес для написання пропозицій щодо покращення Python (PEP), змодельований на основі процесу RFC в Інтернеті. PEPs — це проекти документів, які описують запропоновану нову функцію, і постійно переглядаються, доки спільнота не досягне консенсусу, прийняти або відхилити пропозицію. Цитата зі вступу до PEP 1, «Мета PEP і рекомендації»:

> PEP розшифровується як Python Enhancement Proposal. PEP — це проектний документ, який надає інформацію спільноті Python або описує нову функцію для Python. PEP має надавати стислу технічну специфікацію функції та обґрунтування цієї функції.

> Ми плануємо, щоб PEP були основними механізмами для пропонування нових функцій, для збору внесків спільноти щодо проблеми та для документування дизайнерських рішень, які увійшли до Python. Автор PEP відповідає за формування консенсусу в спільноті та документування особливих думок.

Read the rest of PEP 1 for the details of the PEP editorial process, style, and format. PEPs are kept in the Python CVS tree on SourceForge, though they’re not part of the Python 2.0 distribution, and are also available in HTML form from https://peps.python.org/. As of September 2000, there are 25 PEPs, ranging from PEP 201, «Lockstep Iteration», to PEP 225, «Elementwise/Objectwise Operators».

## Unicode

Найбільшою новою функцією Python 2.0 є новий фундаментальний тип даних: рядки Unicode. Юнікод використовує 16-розрядні числа для представлення символів замість 8-розрядних чисел, які використовуються в ASCII, тобто підтримується 65 536 різних символів.

Остаточний інтерфейс для підтримки Unicode був досягнутий під час незліченних, часто бурхливих дискусій у списку розсилки python-dev, і здебільшого реалізований Марком-Андре Лембургом на основі реалізації рядкового типу Unicode Фредріком Лундом. Детальне пояснення інтерфейсу було написано як PEP 100, «Інтеграція Python Unicode». Ця стаття лише охопить найважливіші моменти щодо інтерфейсів Unicode.

In Python source code, Unicode strings are written as `u"string"`. Arbitrary Unicode characters can be written using a new escape sequence, `\uHHHH`, where HHHH is a 4-digit hexadecimal number from 0000 to FFFF. The existing `\xHH` escape sequence can also be used, and octal escapes can be used for characters up to U+01FF, which is represented by `\777`.

Рядки Unicode, як і звичайні рядки, є незмінним типом послідовності. Їх можна індексувати та нарізати, але не змінювати на місці. Рядки Unicode мають метод `encode( [encoding] )`, який повертає 8-бітовий рядок у потрібному кодуванні. Кодування називаються рядками, наприклад `'ascii'`, `'utf-8''`, `'iso-8859-1''` або будь-яким іншим. Кодек API визначено для реалізації та реєстрації нових кодувань, які потім доступні в усій програмі 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 — звичайний рядок із 1 символу або 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')` повертає 2-символьний рядок „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 і повертає 2-кортеж `(рядок, довжина)`. рядок — це 8-бітовий рядок, що містить частину (можливо, весь) рядка Юнікод, перетвореного в дане кодування, а довжина вказує вам, яку частину рядка Юнікод було перетворено.

- decode_func є протилежністю encode_func, беручи 8-бітний рядок і повертаючи 2-кортеж `(ustring, length)`, що складається з результуючого рядка Unicode ustring і цілого числа length, що повідомляє, як велика частина 8-бітного рядка була спожита.

- stream_reader is a class that supports decoding input from a stream. stream_reader(file_obj) returns an object that supports the `read()`, `readline()`, and `readlines()` methods. These methods will all translate from the given encoding and return Unicode strings.

- stream_writer, similarly, is a class that supports encoding output to a stream. stream_writer(file_obj) returns an object that supports the `write()` and `writelines()` methods. These methods expect Unicode strings, translating them to the given encoding on output.

Наприклад, наступний код записує рядок 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 на майбутнє, оскільки деякі майбутні версії Python можуть відмовитися від підтримки 8-бітних рядків і надавати лише рядки Unicode.

## Розуміння списку

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

Існуючі функції `map()` і `filter()` можна використовувати для цієї мети, але вони потребують функції як один із своїх аргументів. Це добре, якщо існує вбудована функція, яку можна передати напряму, але якщо її немає, вам доведеться створити невелику функцію для виконання необхідної роботи, а правила визначення області Python роблять результат негарним, якщо маленька функція потребує Додаткова інформація. Розглянемо перший приклад із попереднього абзацу, знайшовши всі рядки у списку, що містить заданий підрядок. Щоб це зробити, ви можете написати наступне:

    # Given the list L, make a list of all strings
    # containing the substring 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` містять послідовності, які потрібно повторити. Послідовності не обов’язково мають бути однакової довжини, тому що вони не повторюються паралельно, а зліва направо; це більш чітко пояснюється в наступних параграфах. Елементи згенерованого списку будуть послідовними значеннями виразу. Останній пункт `if` необов’язковий; якщо присутнє, вираз обчислюється та додається до результату, лише якщо умова істинна.

Щоб зробити семантику дуже зрозумілою, розуміння списку еквівалентно наступному коду Python:

    for expr1 in sequence1:
        for expr2 in sequence2:
        ...
            for exprN in sequenceN:
                 if (condition):
                      # Append the value of
                      # the expression to the
                      # resulting list.

Це означає, що коли є кілька пропозицій `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, якщо вираз створює кортеж, його потрібно взяти в дужки. Перше розуміння списку нижче є синтаксичною помилкою, тоді як друге є правильним:

    # Syntax error
    [ x,y for x in seq1 for y in seq2]
    # Correct
    [ (x,y) for x in seq1 for y in seq2]

Ідея розуміння списків спочатку походить від функціональної мови програмування Haskell (https://www.haskell.org). Ґреґ Юінг найбільш ефективно доводив доцільність додавання їх до Python і написав початковий патч для розуміння списку, який потім, здавалося, нескінченний час обговорювався в списку розсилки python-dev і постійно оновлювався Скіпом Монтанаро.

## Доповнене завдання

До Python 2.0 додано розширені оператори присвоєння, ще одну давно запитувану функцію. Розширені оператори присвоєння включають `+=`, `-=`, `*=` і так далі. Наприклад, оператор `a += 2` збільшує значення змінної `a` на 2, еквівалентно трохи довшому `a = a + 2`.

The full list of supported assignment operators is `+=`, `-=`, `*=`, `/=`, `%=`, `**=`, `&=`, `|=`, `^=`, `>>=`, and `<<=`. Python classes can override the augmented assignment operators by defining methods named `__iadd__()`, `__isub__()`, etc. For example, the following `Number` class stores a number and supports using += to create a new instance with an incremented value.

    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

The `__iadd__()` special method is called with the value of the increment, and should return a new instance with an appropriately modified value; this return value is bound as the new value of the variable on the left-hand side.

Розширені оператори присвоєння вперше були представлені в мові програмування C, і більшість похідних від C мов, таких як awk, C++, Java, Perl і PHP, також їх підтримують. Патч доповненого призначення реалізував Томас Воутерс.

## Рядкові методи

Until now string-manipulation functionality was in the `string` module, which was usually a front-end for the `strop` module written in C. The addition of Unicode posed a difficulty for the `strop` module, because the functions would all need to be rewritten in order to accept either 8-bit or Unicode strings. For functions such as `string.replace()`, which takes 3 string arguments, that means eight possible permutations, and correspondingly complicated code.

Натомість Python 2.0 переносить проблему на рядковий тип, роблячи функціональні можливості маніпулювання рядками доступними через методи як для 8-бітних рядків, так і для рядків Unicode.

    >>> 'andrew'.capitalize()
    'Andrew'
    >>> 'hostname'.replace('os', 'linux')
    'hlinuxtname'
    >>> 'moshe'.find('sh')
    2

Одне, незважаючи на першоквітневий жарт, не змінилося, це те, що рядки Python є незмінними. Таким чином, рядкові методи повертають нові рядки і не змінюють рядок, з яким вони працюють.

Старий модуль `string` все ще доступний для зворотної сумісності, але він здебільшого діє як інтерфейс для нових методів рядків.

Two methods which have no parallel in pre-2.0 versions, although they did exist in JPython for quite some time, are `startswith()` and `endswith()`. `s.startswith(t)` is equivalent to `s[:len(t)] == t`, while `s.endswith(t)` is equivalent to `s[-len(t):] == t`.

One other method which deserves special mention is `join()`. The `join()` method of a string receives one parameter, a sequence of strings, and is equivalent to the `string.join()` function from the old `string` module, with the arguments reversed. In other words, `s.join(seq)` is equivalent to the old `string.join(seq, s)`.

## Збирання сміття циклів

Реалізація Python на C використовує підрахунок посилань для реалізації збирання сміття. Кожен об’єкт Python підтримує підрахунок кількості посилань, що вказують на нього самого, і коригує кількість у міру створення чи знищення посилань. Коли кількість посилань досягає нуля, об’єкт більше не доступний, оскільки для доступу до нього потрібно мати посилання на об’єкт, і якщо кількість посилань дорівнює нулю, посилань більше не існує.

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

Розглянемо найпростіший можливий цикл, екземпляр класу, який має посилання на самого себе:

    instance = SomeClass()
    instance.myself = instance

Після виконання двох вищезазначених рядків коду кількість посилань `примірника` дорівнює 2; одне посилання походить від змінної з назвою `'instance'`, а інше — від атрибута `mysel` екземпляра.

Що станеться, якщо наступним рядком коду є `del instance`? Кількість посилань `примірника` зменшено на 1, тому він має кількість посилань 1; посилання в атрибуті `mysel` все ще існує. Проте екземпляр більше не доступний через код Python, і його можна видалити. Кілька об’єктів можуть брати участь у циклі, якщо вони мають посилання один на одного, що спричиняє витік усіх об’єктів.

Python 2.0 вирішує цю проблему, періодично виконуючи алгоритм виявлення циклу, який шукає недоступні цикли та видаляє залучені об’єкти. Новий модуль `gc` надає функції для збирання сміття, отримання статистики налагодження та налаштування параметрів збирача.

Виконання алгоритму виявлення циклу займає деякий час, а тому призведе до додаткових витрат. Сподіваємося, що після того, як ми отримаємо досвід роботи зі збором циклів від використання 2.0, Python 2.1 зможе мінімізувати накладні витрати завдяки ретельному налаштуванню. Поки що неочевидно, скільки продуктивності втрачається, тому що це порівняльний аналіз є складним і дуже залежить від того, як часто програма створює та знищує об’єкти. Виявлення циклів можна вимкнути під час компіляції Python, якщо ви не можете дозволити собі навіть незначне зниження швидкості або підозрюєте, що збирання циклів є помилковим, вказавши перемикач `--without-cycle-gc`, коли виконання сценарію configure.

Кілька людей взялися за цю проблему та зробили свій внесок у її вирішення. Рання реалізація підходу виявлення циклу була написана Тобі Келсі. Поточний алгоритм був запропонований Еріком Тідеманном під час візиту до CNRI, а Гвідо ван Россум і Ніл Шеменауер написали дві різні реалізації, які пізніше були інтегровані Нілом. Багато інших людей пропонували пропозиції на цьому шляху; архіви списку розсилки python-dev за березень 2000 року містять більшість відповідних обговорень, особливо в темах під назвою «Колекція довідкового циклу для Python» і «Знову завершення».

## Інші основні зміни

У синтаксис і вбудовані функції Python внесено різні незначні зміни. Жодна зі змін не є дуже далекосяжною, але це зручні зручності.

### Незначні зміни мови

A new syntax makes it more convenient to call a given function with a tuple of arguments and/or a dictionary of keyword arguments. In Python 1.5 and earlier, you’d use the `apply()` built-in function: `apply(f, args, kw)` calls the function `f()` with the argument tuple args and the keyword arguments in the dictionary kw. `apply()` is the same in 2.0, but thanks to a patch from Greg Ewing, `f(*args, **kw)` is a shorter and clearer way to achieve the same effect. This syntax is symmetrical with the syntax for defining functions:

    def f(*args, **kw):
        # args is a tuple of positional args,
        # kw is a dictionary of keyword args
        ...

The `print` statement can now have its output directed to a file-like object by following the `print` with `>> file`, similar to the redirection operator in Unix shells. Previously you’d either have to use the `write()` method of the file-like object, which lacks the convenience and simplicity of `print`, or you could assign a new value to `sys.stdout` and then restore the old value. For sending output to standard error, it’s much easier to write this:

    print >> sys.stderr, "Warning: action field not supplied"

Модулі тепер можна перейменовувати під час їх імпорту, використовуючи синтаксис `імпортувати модуль як ім’я` або `з імені імпорту модуля як інше ім’я`. Патч надіслав Томас Воутерс.

Новий стиль формату доступний при використанні оператора `%`; „%r“ вставить `repr()` свого аргументу. Це також було додано з міркувань симетрії, цього разу для симетрії з існуючим стилем формату „%s“, який вставляє `str()` свого аргументу. Наприклад, `'%r %s' % ('abc', 'abc')` повертає рядок, що містить `'abc' abc`.

Previously there was no way to implement a class that overrode Python’s built-in `in` operator and implemented a custom version. `obj in seq` returns true if obj is present in the sequence seq; Python computes this by simply trying every index of the sequence until either obj is found or an `IndexError` is encountered. Moshe Zadka contributed a patch which adds a `__contains__()` magic method for providing a custom implementation for `in`. Additionally, new built-in objects written in C can define what `in` means for them via a new slot in the sequence protocol.

Попередні версії Python використовували рекурсивний алгоритм для видалення об’єктів. Глибоко вкладені структури даних можуть спричинити заповнення стека C і збій інтерпретатора; Крістіан Тісмер переписав логіку видалення, щоб вирішити цю проблему. У зв’язку з цим, порівняння рекурсивних об’єктів нескінченно рекурсувало і вийшло з ладу; Джеремі Гілтон переписав код, щоб він більше не виходив з ладу, натомість створюючи корисний результат. Наприклад, після цього коду:

    a = []
    b = []
    a.append(a)
    b.append(b)

The comparison `a==b` returns true, because the two recursive data structures are isomorphic. See the thread «trashcan and PR#7» in the April 2000 archives of the python-dev mailing list for the discussion leading up to this implementation, and some useful relevant links. Note that comparisons can now also raise exceptions. In earlier versions of Python, a comparison operation such as `cmp(a,b)` would always produce an answer, even if a user-defined `__cmp__()` method encountered an error, since the resulting exception would simply be silently swallowed.

Work has been done on porting Python to 64-bit Windows on the Itanium processor, mostly by Trent Mick of ActiveState. (Confusingly, `sys.platform` is still `'win32'` on Win64 because it seems that for ease of porting, MS Visual C++ treats code as 32 bit on Itanium.) PythonWin also supports Windows CE; see the Python CE page at https://pythonce.sourceforge.net/ for more information.

Ще одна нова платформа — 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 має неправильний відступ.

### Зміни вбудованих функцій

Додано нову вбудовану функцію `zip(seq1, seq2, ...)`. `zip()` повертає список кортежів, де кожен кортеж містить i-й елемент із кожної послідовності аргументів. Різниця між `zip()` і `map(None, seq1, seq2)` полягає в тому, що `map()` доповнює послідовності `None`, якщо послідовності не мають однакову довжину , а `zip()` скорочує повернутий список до довжини найкоротшої послідовності аргументів.

The `int()` and `long()` functions now accept an optional «base» parameter when the first argument is a string. `int('123', 10)` returns 123, while `int('123', 16)` returns 291. `int(123, 16)` raises a `TypeError` exception with the message «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, 'бета', 1)`. level — це рядок, наприклад `"alpha"`, `"beta"` або `"final"` для остаточного випуску.

Dictionaries have an odd new method, `setdefault(key, default)`, which behaves similarly to the existing `get()` method. However, if the key is missing, `setdefault()` both returns the value of default as `get()` would do, and also inserts it into the dictionary as the value for key. Thus, the following lines of code:

    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

Нові випуски Python намагаються бути сумісними з попередніми випусками, і результати були досить хорошими. Однак деякі зміни вважаються досить корисними, зазвичай тому, що вони виправляють початкові дизайнерські рішення, які виявилися активно помилковими, тому порушення зворотної сумісності не завжди можна уникнути. У цьому розділі перераховано зміни в Python 2.0, які можуть призвести до поломки старого коду Python.

The change which will probably break the most code is tightening up the arguments accepted by some methods. Some methods would take multiple arguments and treat them as a tuple, particularly various list methods such as `append()` and `insert()`. In earlier versions of Python, if `L` is a list, `L.append( 1,2 )` appends the tuple `(1,2)` to the list. In Python 2.0 this causes a `TypeError` exception to be raised, with the message: „append requires exactly 1 argument; 2 given“. The fix is to simply add an extra set of parentheses to pass both values as a tuple: `L.append( (1,2) )`.

The earlier versions of these methods were more forgiving because they used an old function in Python’s C interface to parse their arguments; 2.0 modernizes them to use `PyArg_ParseTuple()`, the current argument parsing function, which provides more helpful error messages and treats multi-argument calls as errors. If you absolutely must use 2.0 but can’t fix your code, you can edit `Objects/listobject.c` and define the preprocessor symbol `NO_STRICT_LIST_APPEND` to preserve the old behaviour; this isn’t recommended.

Some of the functions in the `socket` module are still forgiving in this way. For example, `socket.connect( ('hostname', 25) )` is the correct form, passing a tuple representing an IP address, but `socket.connect('hostname', 25)` also works. `socket.connect_ex` and `socket.bind` are similarly easy-going. 2.0alpha1 tightened these functions up, but because the documentation actually used the erroneous multiple argument form, many people wrote code which would break with the stricter checking. GvR backed out the changes in the face of public reaction, so for the `socket` module, the documentation was fixed and the multiple argument form is simply marked as deprecated; it will be tightened up again in a future Python version.

Екранування `\x` у рядкових літералах тепер займає рівно 2 шістнадцяткові цифри. Раніше він використовував усі шістнадцяткові цифри після „x“ і брав молодші 8 бітів результату, тому `\x123456` був еквівалентним `\x56`.

Винятки `AttributeError` і `NameError` мають більш зрозуміле повідомлення про помилку, текст якого буде приблизно таким, як «Екземпляр спаму» не має атрибута «яйця» або «назва «яйця» є не визначено. Раніше повідомленням про помилку було лише відсутнє ім’я атрибута `яйця`, і код, написаний для використання цього факту, зламається у 2.0.

Some work has been done to make integers and long integers a bit more interchangeable. In 1.5.2, large-file support was added for Solaris, to allow reading files larger than 2 GiB; this made the `tell()` method of file objects return a long integer instead of a regular integer. Some code would subtract two file offsets and attempt to use the result to multiply a sequence or slice a string, but this raised a `TypeError`. In 2.0, long integers can be used to multiply or slice a sequence, and it’ll behave as you’d intuitively expect it to; `3L * 'abc'` produces „abcabcabc“, and `(0,1,2,3)[2L:4L]` produces (2,3). Long integers can also be used in various contexts where previously only integers were accepted, such as in the `seek()` method of file objects, and in the formats supported by the `%` operator (`%d`, `%i`, `%x`, etc.). For example, `"%d" % 2L**64` will produce the string `18446744073709551616`.

Найтонша зміна довгого цілого числа полягає в тому, що `str()` довгого цілого більше не має кінцевого символу „L“, хоча `repr()` все ще містить його. «L» дратувала багатьох людей, які хотіли надрукувати довгі цілі числа, які виглядали так само, як звичайні цілі числа, оскільки їм доводилося докладати всіх зусиль, щоб відрізати символ. Це більше не є проблемою у 2.0, але код, який виконує `str(longval)[:-1]` і припускає, що є „L“, тепер втратить останню цифру.

Taking the `repr()` of a float now uses a different formatting precision than `str()`. `repr()` uses `%.17g` format string for C’s `sprintf()`, while `str()` uses `%.12g` as before. The effect is that `repr()` may occasionally show more decimal places than `str()`, for certain numbers. For example, the number 8.1 can’t be represented exactly in binary, so `repr(8.1)` is `'8.0999999999999996'`, while str(8.1) is `'8.1'`.

The `-X` command-line option, which turned all standard exceptions into strings instead of classes, has been removed; the standard exceptions will now always be classes. The `exceptions` module containing the standard exceptions was translated from Python to a built-in C module, written by Barry Warsaw and Fredrik Lundh.

## Розширення/вбудовування змін

Деякі зміни знаходяться під обкладинками, і вони будуть очевидні лише для людей, які пишуть модулі розширення C або вбудовують інтерпретатор Python у більшу програму. Якщо ви не маєте справу з API C Python, можете сміливо пропустити цей розділ.

Номер версії Python C API було збільшено, тому розширення C, скомпільовані для 1.5.2, потрібно перекомпілювати, щоб працювати з 2.0. У Windows Python 2.0 не може імпортувати стороннє розширення, створене для Python 1.5.x, через те, як працюють бібліотеки DLL Windows, тому Python викличе виняток, і імпорт не вдасться.

Користувачі модуля ExtensionClass Джима Фултона будуть раді дізнатися, що були додані хуки, завдяки чому ExtensionClasses тепер підтримуються `isinstance()` і `issubclass()`. Це означає, що вам більше не потрібно пам’ятати про написання такого коду, як `if type(obj) == myExtensionClass`, а можна використовувати більш природний `if isinstance(obj, myExtensionClass)`.

Файл `Python/importdl.c`, який являв собою масу #ifdefs для підтримки динамічного завантаження на багатьох різних платформах, був очищений і реорганізований Грегом Стайном. `importdl.c` тепер досить малий, і специфічний для платформи код було переміщено до групи файлів `Python/dynload_*.c`. Ще одне очищення: у каталозі Include/ також було кілька файлів `my*.h`, які містили різноманітні хаки для перенесення; їх об’єднано в один файл `Include/pyport.h`.

Vladimir Marangozov’s long-awaited malloc restructuring was completed, to make it easy to have the Python interpreter use a custom allocator instead of C’s standard `malloc()`. For documentation, read the comments in `Include/pymem.h` and `Include/objimpl.h`. For the lengthy discussions during which the interface was hammered out, see the web archives of the „patches“ and „python-dev“ lists at python.org.

Останні версії середовища розробки GUSI для MacOS підтримують потоки POSIX. Таким чином, підтримка потоків Python POSIX тепер працює на 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, стикаються з цим обмеженням. Патч від Charles G. Waldman підвищує ліміт з `2**16` до `2**32`.

Three new convenience functions intended for adding constants to a module’s dictionary at module initialization time were added: `PyModule_AddObject()`, `PyModule_AddIntConstant()`, and `PyModule_AddStringConstant()`. Each of these functions takes a module object, a null-terminated C string containing the name to be added, and a third argument for the value to be assigned to the name. This third argument is, respectively, a Python object, a C long, or a C string.

A wrapper API was added for Unix-style signal handlers. `PyOS_getsig()` gets a signal handler and `PyOS_setsig()` will set a new handler.

## Distutils: полегшення встановлення модулів

До Python 2.0 встановлення модулів було нудною справою — не було можливості автоматично визначити, де встановлено Python, або які параметри компілятора використовувати для модулів розширення. Авторам програмного забезпечення довелося пройти через важкий ритуал редагування файлів Makefile та конфігураційних файлів, які справді працюють лише в Unix, а Windows і MacOS не підтримуються. Користувачі Python зіткнулися з надзвичайно різними інструкціями встановлення, які відрізнялися між різними пакетами розширень, що робило адміністрування встановлення Python чимось на зразок клопітку.

The SIG for distribution utilities, shepherded by Greg Ward, has created the Distutils, a system to make package installation much easier. They form the `distutils` package, a new part of Python’s standard library. In the best case, installing a Python module from source will require the same steps: first you simply mean unpack the tarball or zip archive, and the run «`python setup.py install`». The platform will be automatically detected, the compiler will be recognized, C extension modules will be compiled, and the distribution installed into the proper directory. Optional command-line arguments provide more control over the installation process, the distutils package offers many places to override defaults – separating the build from the install, building or installing in non-default directories, and more.

Щоб використовувати 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» і «bdist_wininst» вже були використані для створення дистрибутива RPM і інсталятора Windows для програмного забезпечення відповідно.

Усе це задокументовано в новому посібнику Розповсюдження модулів Python, який доповнює базовий набір документації Python.

## Модулі XML

Python 1.5.2 included a simple XML parser in the form of the `xmllib` module, contributed by Sjoerd Mullender. Since 1.5.2’s release, two different interfaces for processing XML have become common: SAX2 (version 2 of the Simple API for XML) provides an event-driven interface with some similarities to `xmllib`, and the DOM (Document Object Model) provides a tree-based interface, transforming an XML document into a tree of nodes that can be traversed and modified. Python 2.0 includes a SAX2 interface and a stripped-down DOM interface as part of the `xml` package. Here we will give a brief overview of these new interfaces; consult the Python documentation or the source code for complete details. The Python XML SIG is also working on improved documentation.

### Підтримка SAX2

SAX defines an event-driven interface for parsing XML. To use SAX, you must write a SAX handler class. Handler classes inherit from various classes provided by SAX, and override various methods that will then be called by the XML parser. For example, the `startElement()` and `endElement()` methods are called for every starting and end tag encountered by the parser, the `characters()` method is called for every chunk of character data, and so forth.

Перевага керованого подіями підходу полягає в тому, що весь документ не повинен постійно зберігатися в пам’яті в будь-який момент часу, що має значення, якщо ви обробляєте дійсно великі документи. Однак написання класу обробника 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

    # Create a parser object
    parser = sax.make_parser()

    # Tell it what handler to use
    handler = SimpleHandler()
    parser.setContentHandler( handler )

    # Parse a file!
    parser.parse( 'hamlet.xml' )

For more information, consult the Python documentation, or the XML HOWTO at https://pyxml.sourceforge.net/topics/howto/xml-howto.html.

### Підтримка DOM

The Document Object Model is a tree-based representation for an XML document. A top-level `Document` instance is the root of the tree, and has a single child which is the top-level `Element` instance. This `Element` has children nodes representing character data and any sub-elements, which may have further children of their own, and so forth. Using the DOM you can traverse the resulting tree any way you like, access element and attribute values, insert and delete nodes, and convert the tree back into XML.

DOM корисний для модифікації XML-документів, оскільки ви можете створити дерево DOM, змінити його, додавши нові вузли або перевпорядкувавши піддерева, а потім створити новий XML-документ як результат. Ви також можете побудувати дерево DOM вручну та перетворити його на XML, що може бути більш гнучким способом створення виводу XML, ніж просто запис `<tag1>`…`</tag1>` у файл.

The DOM implementation included with Python lives in the `xml.dom.minidom` module. It’s a lightweight implementation of the Level 1 DOM with support for XML namespaces. The `parse()` and `parseString()` convenience functions are provided for generating a DOM tree:

    from xml.dom import minidom
    doc = minidom.parse('hamlet.xml')

`doc` is a `Document` instance. `Document`, like all the other DOM classes such as `Element` and `Text`, is a subclass of the `Node` base class. All the nodes in a DOM tree therefore support certain common methods, such as `toxml()` which returns a string containing the XML representation of the node and its children. Each class also has special methods of its own; for example, `Element` and `Document` instances have a method to find all child elements with a given tag name. Continuing from the previous 2-line example:

    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

    # Remove the first child
    root.removeChild( root.childNodes[0] )

    # Move the new first child to the end
    root.appendChild( root.childNodes[0] )

    # Insert the new first child (originally,
    # the third child) before the 20th child.
    root.insertBefore( root.childNodes[0], root.childNodes[20] )

Again, I will refer you to the Python documentation for a complete listing of the different `Node` classes and their various methods.

### Відношення до PyXML

Група спеціальних інтересів XML деякий час працювала над кодом Python, пов’язаним із XML. Його розповсюдження коду під назвою PyXML доступне на веб-сторінках SIG за адресою https://www.python.org/community/sigs/current/xml-sig. Дистрибутив PyXML також використовував назву пакета `xml`. Якщо ви писали програми, які використовували PyXML, ви, ймовірно, цікавитеся його сумісністю з пакетом 2.0 `xml`.

Відповідь полягає в тому, що пакет `xml` Python 2.0 несумісний з PyXML, але його можна зробити сумісним, встановивши останню версію PyXML. Багато програм можуть обійтися підтримкою XML, яка включена в Python 2.0, але складніші програми вимагають інсталяції повного пакета PyXML. Після встановлення PyXML версії 0.6.0 або новішої замінить пакет `xml`, який постачається разом із Python, і стане строгим доповненням до стандартного пакета, додаючи купу додаткових функцій. Деякі з додаткових функцій у PyXML включають:

- 4DOM, повна реалізація DOM від FourThought, Inc.

- Парсер перевірки xmlproc, написаний Ларсом Маріусом Гаршолом.

- The `sgmlop` parser accelerator module, written by Fredrik Lundh.

## Зміни модуля

Lots of improvements and bugfixes were made to Python’s extensive standard library; some of the affected modules include `readline`, `ConfigParser`, `cgi`, `calendar`, `posix`, `readline`, `xmllib`, `aifc`, `chunk`, `wave`, `random`, `shelve`, and `nntplib`. Consult the CVS logs for the exact patch-by-patch details.

Brian Gallew contributed OpenSSL support for the `socket` module. OpenSSL is an implementation of the Secure Socket Layer, which encrypts the data being sent over a socket. When compiling Python, you can edit `Modules/Setup` to include SSL support, which adds an additional function to the `socket` module: `socket.ssl(socket, keyfile, certfile)`, which takes a socket object and returns an SSL socket. The `httplib` and `urllib` modules were also changed to support `https://` URLs, though no one has implemented FTP or SMTP over SSL.

The `httplib` module has been rewritten by Greg Stein to support HTTP/1.1.

Backward compatibility with the 1.5 version of `httplib` is provided, though using HTTP/1.1 features such as pipelining will require rewriting code to use a different set of interfaces.

The `Tkinter` module now supports Tcl/Tk version 8.1, 8.2, or 8.3, and support for the older 7.x versions has been dropped. The Tkinter module now supports displaying Unicode strings in Tk widgets. Also, Fredrik Lundh contributed an optimization which makes operations like `create_line` and `create_polygon` much faster, especially when using lots of coordinates.

Модуль `curses` було значно розширено, починаючи з розширеної версії Олівера Андріча, щоб забезпечити багато додаткових функцій від ncurses і проклять SYSV, таких як колір, підтримка альтернативного набору символів, підтримка панелей і миші. Це означає, що модуль більше не сумісний з операційними системами, які мають лише прокляття BSD, але, здається, на даний момент немає жодної ОС, яка підпадає під цю категорію.

Як згадувалося в попередньому обговоренні підтримки Unicode 2.0, базову реалізацію регулярних виразів, які надає модуль `re`, було змінено. SRE, нова система регулярних виразів, написана Фредріком Лундом і частково фінансована Hewlett Packard, підтримує зіставлення як з 8-бітними рядками, так і з рядками Unicode.

## Нові модулі

Додано ряд нових модулів. Ми просто перерахуємо їх із короткими описами; зверніться до документації 2.0, щоб дізнатися більше про конкретний модуль.

- `atexit`: для реєстрації функцій, які будуть викликані до завершення роботи інтерпретатора Python. Код, який наразі безпосередньо встановлює `sys.exitfunc`, слід змінити, щоб замість нього використовувати модуль `atexit`, імпортуючи `atexit` і викликаючи `atexit.register()` із функцією, яку потрібно викликати на виході. (Надав Скіп Монтанаро.)

- `codecs`, `encodings`, `unicodedata`: Added as part of the new Unicode support.

- `filecmp`: Supersedes the old `cmp`, `cmpcache` and `dircmp` modules, which have now become deprecated. (Contributed by Gordon MacMillan and Moshe Zadka.)

- `gettext`: Цей модуль забезпечує підтримку інтернаціоналізації (I18N) і локалізації (L10N) для програм Python, надаючи інтерфейс до бібліотеки каталогу повідомлень GNU gettext. (Інтегровано Баррі Варшау, з окремих внесків Мартіна фон Льовіса, Пітера Функа та Джеймса Генстріджа.)

- `linuxaudiodev`: Support for the `/dev/audio` device on Linux, a twin to the existing `sunaudiodev` module. (Contributed by Peter Bosch, with fixes by Jeremy Hylton.)

- `mmap`: Інтерфейс для файлів із відображенням пам’яті як у Windows, так і в Unix. Вміст файлу можна відобразити безпосередньо в пам’яті, після чого він поводиться як змінний рядок, тому його вміст можна читати та змінювати. Їх можна навіть передати функціям, які очікують звичайних рядків, наприклад, модулю `re`. (Надано Семом Рашингом, з деякими розширеннями А. М. Кухлінгом.)

- `pyexpat`: An interface to the Expat XML parser. (Contributed by Paul Prescod.)

- `robotparser`: Parse a `robots.txt` file, which is used for writing web spiders that politely avoid certain areas of a web site. The parser accepts the contents of a `robots.txt` file, builds a set of rules from it, and can then answer questions about the fetchability of a given URL. (Contributed by Skip Montanaro.)

- `tabnanny`: Модуль/скрипт для перевірки вихідного коду Python на неоднозначні відступи. (Надав Тім Пітерс.)

- `UserString`: A base class useful for deriving objects that behave like strings.

- `webbrowser`: модуль, який забезпечує незалежний від платформи спосіб запуску веб-браузера за певною URL-адресою. Для кожної платформи різні браузери пробуються в певному порядку. Користувач може змінити браузер, який запускається, встановивши змінну середовища BROWSER. (Спочатку натхненний патчем Еріка С. Реймонда до `urllib`, який додав подібну функціональність, але остаточний модуль походить від коду, спочатку реалізованого Фредом Дрейком як `Tools/idle/BrowserControl.py`, і адаптованого для стандартна бібліотека Фреда.)

- `_winreg`: An interface to the Windows registry. `_winreg` is an adaptation of functions that have been part of PythonWin since 1995, but has now been added to the core distribution, and enhanced to support Unicode. `_winreg` was written by Bill Tutt and Mark Hammond.

- `zipfile`: Модуль для читання та запису архівів ZIP-формату. Це архіви, створені PKZIP у DOS/Windows або zip в Unix, не плутати з файлами у форматі gzip(які підтримуються модулем `gzip`) (надано Джеймсом К. Алстромом.)

- `imputil`: A module that provides a simpler way for writing customized import hooks, in comparison to the existing `ihooks` module. (Implemented by Greg Stein, with much discussion on python-dev along the way.)

## Покращення IDLE

IDLE — це офіційна кросплатформна IDE Python, написана за допомогою Tkinter. Python 2.0 містить IDLE 0.6, який додає низку нових функцій і покращень. Неповний список:

- Покращення та оптимізація інтерфейсу користувача, особливо в області підсвічування синтаксису та автоматичного відступу.

- Переглядач класів тепер показує більше інформації, наприклад функції верхнього рівня в модулі.

- Ширина вкладки тепер доступна користувачеві. Під час відкриття існуючого файлу Python IDLE автоматично визначає правила відступів і адаптує їх.

- Тепер існує підтримка виклику браузерів на різних платформах, які використовуються для відкриття документації Python у браузері.

- У IDLE тепер є командний рядок, який багато в чому схожий на ванільний інтерпретатор Python.

- У багатьох місцях додано підказки щодо дзвінків.

- IDLE тепер можна встановити як пакет.

- Тепер у вікні редактора внизу є рядок/стовпець.

- Три нові команди натискання клавіш: перевірити модуль (`Alt`-`F5`), імпортувати модуль (`F5`) і запустити сценарій (`Ctrl`-`F5`).

## Видалені та застарілі модулі

A few modules have been dropped because they’re obsolete, or because there are now better ways to do the same thing. The `stdwin` module is gone; it was for a platform-independent windowing toolkit that’s no longer developed.

A number of modules have been moved to the `lib-old` subdirectory: `cmp`, `cmpcache`, `dircmp`, `dump`, `find`, `grep`, `packmail`, `poly`, `util`, `whatsound`, `zmod`. If you have code which relies on a module that’s been moved to `lib-old`, you can simply add that directory to `sys.path` to get them back, but you’re encouraged to update any code that uses these modules.

## Подяки

Автори хотіли б подякувати наступним людям за пропозиції щодо різних чернеток цієї статті: Девід Болен, Марк Хаммонд, Грег Хаузер, Джеремі Гілтон, Фредрік Лунд, Детлеф Ланнерт, Ааз Марух, Скіп Монтанаро, Володимир Марангозов, Тобіас Ползін, Гвідо ван Россум, Ніл Шеменауер і Расс Шмідт.