> **Источник:** https://python-all.ru/3.1/whatsnew/2.1.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

# Что нового в Python 2.1

| Автор: | A.M. Kuchling |
| --- | --- |

## Введение

В этой статье описываются новые возможности Python 2.1. Хотя изменений не так много, как в Python 2.0, она всё же таит несколько приятных сюрпризов. Python 2.1 – первый релиз, управляемый через Python Enhancement Proposals (PEP), поэтому большинство значительных изменений имеют сопровождающие PEP, которые предоставляют более полную документацию и обоснование дизайна. Эта статья не пытается полностью документировать новые возможности, а просто даёт обзор для программистов на Python. Обратитесь к документации Python 2.1 или к соответствующему PEP за более подробной информацией о любой заинтересовавшей вас возможности.

Одной из недавних целей команды разработчиков Python было ускорить темп выпуска новых версий, выпуская новую версию каждые 6–9 месяцев. Python 2.1 стал первым релизом, вышедшим в таком ускоренном темпе: первая альфа-версия появилась в январе, через 3 месяца после финального выпуска Python 2.0.

Финальный выпуск Python 2.1 состоялся 17 апреля 2001 года.

## PEP 227: Вложенные области видимости

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

```python
def f():
    ...
    def g(value):
        ...
        return g(value-1) + 1
    ...
```

Функция `g()` всегда будет вызывать исключение [`NameError`](https://python-all.ru/3.1/library/exceptions.html#NameError), потому что привязка имени `g` не находится ни в её локальном пространстве имён, ни в пространстве имён уровня модуля. На практике это не такая уж большая проблема (как часто вы рекурсивно определяете вложенные функции таким образом?), но это также делало использование выражения [`lambda`](https://python-all.ru/3.1/reference/expressions.html#lambda) более громоздким, и на практике это было проблемой. В коде, использующем [`lambda`](https://python-all.ru/3.1/reference/expressions.html#lambda), часто можно встретить копирование локальных переменных путём передачи их в качестве значений аргументов по умолчанию.

```python
def find(self, name):
    "Return list of any entries equal to 'name'"
    L = filter(lambda x, name=name: x == name,
               self.list_attribute)
    return L
```

В результате удобочитаемость кода Python, написанного в сильно функциональном стиле, сильно страдает.

Самое значительное изменение в Python 2.1 – добавление статической области видимости для решения этой проблемы. Первый эффект: аргумент по умолчанию `name=name` теперь в приведённом выше примере не нужен. Проще говоря, если данной переменной не присвоено значение внутри функции (присваиванием, или операторами [`def`](https://python-all.ru/3.1/reference/compound_stmts.html#def), [`class`](https://python-all.ru/3.1/reference/compound_stmts.html#class) или [`import`](https://python-all.ru/3.1/reference/simple_stmts.html#import)), то ссылки на переменную будут искаться в локальном пространстве имён объемлющей области видимости. Более подробное объяснение правил и разбор реализации можно найти в PEP.

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

Один из побочных эффектов изменения: операторы `from module import *` и `exec` стали недопустимыми внутри области видимости функции при определённых условиях. Справочное руководство по Python всегда утверждало, что `from module import *` допустимо только на верхнем уровне модуля, но интерпретатор CPython ранее этого не проверял. В рамках реализации вложенных областей видимости компилятору, преобразующему исходный код Python в байт-код, необходимо генерировать разный код для доступа к переменным в объемлющей области. `from module import *` и `exec` не позволяют компилятору это определить, поскольку они добавляют в локальное пространство имён имена, неизвестные на этапе компиляции. Поэтому, если функция содержит определения функций или выражения [`lambda`](https://python-all.ru/3.1/reference/expressions.html#lambda) со свободными переменными, компилятор пометит это, возбуждая исключение [`SyntaxError`](https://python-all.ru/3.1/library/exceptions.html#SyntaxError).

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

```python
x = 1
def f():
    # Следующая строка – синтаксическая ошибка
    exec 'x=2'
    def g():
        return x
```

Строка 4, содержащая оператор `exec`, является синтаксической ошибкой, так как `exec` определил бы новую локальную переменную с именем `x`, значение которой должно быть доступно из `g()`.

Это не должно быть большой проблемой, поскольку `exec` редко используется в большинстве программ на Python (а когда используется, это часто признак плохого дизайна).

Из соображений совместимости вложенные области видимости вводились постепенно; в Python 2.1 они не включены по умолчанию, но могут быть включены в модуле с помощью future-выражения, как описано в PEP 236. (См. следующий раздел для дальнейшего обсуждения PEP 236.) В Python 2.2 вложенные области видимости станут использоваться по умолчанию, и их нельзя будет отключить, но у пользователей будет всё время жизни версии 2.1, чтобы исправить любые поломки, вызванные их введением.

> **См. также**
>
> **[**PEP 227**](https://python-all.ru/3.1/whatsnew/2.1.html) – Статически вложенные области видимости**
>
> Написан и реализован Джереми Хилтоном.

## PEP 236: Директивы \_\_future\_\_

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

Синтаксис использует оператор `from...import` с зарезервированным именем модуля [`__future__`](https://python-all.ru/3.1/library/__future__.html#module-__future__). Вложенные области видимости можно включить следующим оператором:

```python
from __future__ import nested_scopes
```

Хотя это выглядит как обычный оператор [`import`](https://python-all.ru/3.1/reference/simple_stmts.html#import), это не так; существуют строгие правила, где может размещаться такой future-оператор. Они могут быть только в начале модуля и должны предшествовать любому коду Python или обычным операторам [`import`](https://python-all.ru/3.1/reference/simple_stmts.html#import). Это связано с тем, что такие операторы могут влиять на то, как компилятор байт-кода Python разбирает код и генерирует байт-код, поэтому они должны предшествовать любым операторам, которые приводят к генерации байт-кода.

> **См. также**
>
> **[**PEP 236**](https://python-all.ru/3.1/whatsnew/2.1.html) – Назад к [`__future__`](https://python-all.ru/3.1/library/__future__.html#module-__future__)**
>
> Написан Тимом Питерсом, в основном реализован Джереми Хилтоном.

## PEP 207: Богатые сравнения

В более ранних версиях поддержка реализации сравнений в пользовательских классах и типах расширения Python была довольно простой. Классы могли реализовать метод `__cmp__()`, которому передавались два экземпляра класса, и он мог вернуть только 0, если они равны, или +1/-1, если нет; метод не мог вызвать исключение или вернуть что-либо, кроме булевого значения. Пользователи Numeric Python часто находили эту модель слишком слабой и ограничивающей, потому что в программах численных расчётов, для которых используется Numeric Python, было бы полезнее выполнять поэлементное сравнение двух матриц, возвращая матрицу с результатами заданного сравнения для каждого элемента. Если две матрицы разного размера, сравнение должно иметь возможность вызвать исключение для сигнализации об ошибке.

В Python 2.1 были добавлены богатые сравнения для поддержки этой потребности. Теперь классы Python могут индивидуально перегружать каждую из операций `<`, `<=`, `>`, `>=`, `==` и `!=`. Новые имена магических методов:

| Операция | Имя метода |
| --- | --- |
| `<` | [`__lt__()`](https://python-all.ru/3.1/reference/datamodel.html#object.__lt__) |
| `<=` | [`__le__()`](https://python-all.ru/3.1/reference/datamodel.html#object.__le__) |
| `>` | [`__gt__()`](https://python-all.ru/3.1/reference/datamodel.html#object.__gt__) |
| `>=` | [`__ge__()`](https://python-all.ru/3.1/reference/datamodel.html#object.__ge__) |
| `==` | [`__eq__()`](https://python-all.ru/3.1/reference/datamodel.html#object.__eq__) |
| `!=` | [`__ne__()`](https://python-all.ru/3.1/reference/datamodel.html#object.__ne__) |

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

Каждый из этих магических методов имеет вид `method(self, other)`, где `self` – объект слева от оператора, а `other` – объект справа. Например, выражение `A < B` вызовет `A.__lt__(B)`.

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

Встроенная функция `cmp(A,B)()` может использовать механизм расширенных сравнений, и теперь принимает необязательный аргумент, указывающий, какую операцию сравнения использовать; он задаётся одной из строк `"<"`, `"<="`, `">"`, `">="`, `"=="` или `"!="`. Если вызвана без необязательного третьего аргумента, `cmp()` вернёт только -1, 0 или +1, как в предыдущих версиях Python; в противном случае она вызовет соответствующий метод и может вернуть любой объект Python.

Есть также соответствующие изменения, интересные программистам на C: новый слот `tp_richcmp` в объектах типов и API для выполнения заданного расширенного сравнения. Я не буду описывать здесь C API, но отсылаю вас к PEP 207 или к документации по C API для Python 2.1 для полного списка связанных функций.

> **См. также**
>
> **[**PEP 207**](https://python-all.ru/3.1/whatsnew/2.1.html) – Расширенные сравнения**
>
> Написан Гвидо ван Россумом, во многом основан на более ранней работе Дэвида Ашера и реализован Гвидо ван Россумом.

## PEP 230: Инфраструктура предупреждений

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

Python 2.1 добавляет инфраструктуру предупреждений (warnings), используемую в этой схеме. Появляется модуль [`warnings`](https://python-all.ru/3.1/library/warnings.html#module-warnings), предоставляющий функции для выдачи предупреждений и фильтрации тех, которые не нужно показывать. Сторонние модули также могут использовать эту инфраструктуру для пометки устаревших возможностей, которые они больше не хотят поддерживать.

Например, в Python 2.1 модуль `regex` является устаревшим, поэтому его импорт вызывает предупреждение:

```python
>>> import regex
__main__:1: DeprecationWarning: the regex module
         is deprecated; please use the re module
>>>
```

Предупреждения можно выдавать вызовом функции [`warnings.warn()`](https://python-all.ru/3.1/library/warnings.html#warnings.warn):

```python
warnings.warn("feature X no longer supported")
```

Первый параметр – сообщение предупреждения; дополнительные необязательные параметры могут использоваться для указания конкретной категории предупреждения.

Можно добавлять фильтры для отключения определённых предупреждений; регулярное выражение может применяться к сообщению или имени модуля, чтобы подавить предупреждение. Например, у вас может быть программа, использующая модуль `regex`, и нет времени прямо сейчас переделывать её на использование модуля [`re`](https://python-all.ru/3.1/library/re.html#module-re). Предупреждение можно подавить вызовом:

```python
import warnings
warnings.filterwarnings(action = 'ignore',
                        message='.*regex module is deprecated',
                        category=DeprecationWarning,
                        module = '__main__')
```

Таким образом добавляется фильтр, который применяется только к предупреждениям класса [`DeprecationWarning`](https://python-all.ru/3.1/library/exceptions.html#DeprecationWarning), возникающим в модуле [`__main__`](https://python-all.ru/3.1/library/__main__.html#module-__main__), и использует регулярное выражение для поиска сообщения об устаревании модуля `regex`; такие предупреждения будут игнорироваться. Предупреждения также могут выводиться только один раз, при каждом выполнении проблемного кода или превращаться в исключения, которые остановят программу (если, конечно, исключения не перехватываются обычным образом).

В C API Python также были добавлены функции для выдачи предупреждений; обратитесь к PEP 230 или документации по API Python за подробностями.

> **См. также**
>
> **[**PEP 5**](https://python-all.ru/3.1/whatsnew/2.1.html) – Руководство по эволюции языка**
>
> Написан Полом Прескодом, чтобы определить процедуры, которым нужно следовать при удалении старых функций из Python. Политика, описанная в этом PEP, официально не принята, но итоговая политика, вероятно, не будет слишком отличаться от предложения Прескода.
>
> **[**PEP 230**](https://python-all.ru/3.1/whatsnew/2.1.html) – Инфраструктура предупреждений**
>
> Написан и реализован Гвидо ван Россумом.

## PEP 229: Новая система сборки

При компиляции Python пользователю приходилось вручную редактировать файл `Modules/Setup`, чтобы включить различные дополнительные модули; набор по умолчанию относительно невелик и ограничен модулями, компилируемыми на большинстве платформ Unix. Это означает, что на платформах Unix с гораздо большими возможностями, особенно на Linux, установки Python часто не содержат всех полезных модулей, которые могли бы быть.

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

Вместо редактирования файла `Modules/Setup` для включения модулей во время сборки запускается скрипт `setup.py` из корневого каталога дистрибутива исходного кода Python, который пытается определить, какие модули можно включить, проверяя модули и заголовочные файлы в системе. Если модуль сконфигурирован в `Modules/Setup`, скрипт `setup.py` не будет пытаться скомпилировать этот модуль и доверится содержимому файла `Modules/Setup`. Это позволяет указать любые необычные флаги командной строки или библиотеки, необходимые для конкретной платформы.

В ещё одном далеко идущем изменении механизма сборки Нил Шеменауэр (Neil Schemenauer) перестроил структуру так, что Python теперь использует один makefile, не являющийся рекурсивным, вместо makefile в корневом каталоге и в каждом из подкаталогов `Python/`, `Parser/`, `Objects/` и `Modules/`. Это ускоряет сборку Python, а также делает взлом Makefile более понятным и простым.

> **См. также**
>
> **[**PEP 229**](https://python-all.ru/3.1/whatsnew/2.1.html) – Использование Distutils для сборки Python**
>
> Автор и разработчик: Э.М. Кухлинг.

## PEP 205: Слабые ссылки

Слабые ссылки, доступные через модуль [`weakref`](https://python-all.ru/3.1/library/weakref.html#module-weakref), – небольшой, но полезный новый тип данных в арсенале программиста на Python.

Хранение ссылки на объект (скажем, в словаре или списке) имеет побочный эффект: объект остаётся живым навсегда. Есть несколько конкретных случаев, когда такое поведение нежелательно; наиболее распространённый – кэши объектов, а другой – циклические ссылки в структурах данных, таких как деревья.

Например, рассмотрим мемоизирующую функцию, которая кэширует результаты другой функции `f(x)()`, сохраняя её аргумент и результат в словаре:

```python
_cache = {}
def memoize(x):
    if _cache.has_key(x):
        return _cache[x]

    retval = f(x)

    # Кэшировать возвращаемый объект
    _cache[x] = retval

    return retval
```

Эта версия работает для простых вещей, таких как целые числа, но у неё есть побочный эффект: словарь `_cache` хранит ссылки на возвращаемые значения, поэтому они никогда не будут освобождены до завершения процесса Python и очистки памяти. Для целых чисел это не очень заметно, но если `f()` возвращает объект или структуру данных, занимающую много памяти, это может стать проблемой.

Слабые ссылки позволяют реализовать кэш, который не будет удерживать объекты в памяти дольше их времени. Если объект доступен только через слабые ссылки, он будет освобождён, и слабые ссылки укажут, что объект, на который они ссылались, больше не существует. Слабая ссылка на объект *obj* создаётся вызовом `wr = weakref.ref(obj)`. Объект, на который ссылаются, возвращается при вызове слабой ссылки как функции: `wr()`. Она вернёт объект, на который ссылается, или `None`, если объект больше не существует.

Это позволяет написать функцию `memoize()`, кеш которой не удерживает объекты в памяти, сохраняя в нём слабые ссылки.

```python
_cache = {}
def memoize(x):
    if _cache.has_key(x):
        obj = _cache[x]()
        # Если объект слабой ссылки всё ещё существует,
        # вернуть его
        if obj is not None: return obj

    retval = f(x)

    # Кэшировать слабую ссылку
    _cache[x] = weakref.ref(retval)

    return retval
```

Модуль [`weakref`](https://python-all.ru/3.1/library/weakref.html#module-weakref) также позволяет создавать объекты-посредники (proxy), которые ведут себя как слабые ссылки – объект, на который ссылаются только такие посредники, удаляется из памяти, – но вместо явного вызова для получения объекта посредник прозрачно перенаправляет все операции на объект, пока он существует. Если объект удалён, попытка использовать посредник вызовет исключение [`weakref.ReferenceError`](https://python-all.ru/3.1/library/weakref.html#weakref.ReferenceError).

```python
proxy = weakref.proxy(obj)
proxy.attr   # Эквивалентно obj.attr
proxy.meth() # Эквивалентно obj.meth()
del obj
proxy.attr   # вызывает weakref.ReferenceError
```

> **См. также**
>
> **[**PEP 205**](https://python-all.ru/3.1/whatsnew/2.1.html) – слабые ссылки**
>
> Автор и разработчик: Фред Л. Дрейк-младший.

## PEP 232: Атрибуты функций

В Python 2.1 к функциям можно прикреплять произвольную информацию. Раньше часто использовали строки документации для хранения информации о функциях и методах, потому что атрибут `__doc__` был единственным способом связать с функцией какие-либо данные. Например, в сервере веб-приложений Zope функции помечались как безопасные для публичного доступа с помощью строки документации, а в фреймворке SPARK Джона Айкока строки документации содержат части BNF-грамматики для разбора. Такая перегрузка неудачна, поскольку строки документации на самом деле предназначены для хранения документации функции; например, это означает, что невозможно корректно документировать функции, предназначенные для частного использования в Zope.

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

```python
def f(): pass

f.publish = 1
f.secure = 1
f.grammar = "A ::= B (C D)*"
```

Словарь, содержащий атрибуты, можно получить как `__dict__` функции. В отличие от атрибута `__dict__` экземпляров классов, у функций можно присвоить новый словарь `__dict__`, хотя новое значение должно быть обычным словарём Python; *нельзя* использовать трюки и присваивать, например, экземпляр `UserDict` или любой другой объект, который ведёт себя как отображение.

> **См. также**
>
> **[**PEP 232**](https://python-all.ru/3.1/whatsnew/2.1.html) – Атрибуты функций**
>
> Автор и разработчик: Барри Уорсо.

## PEP 235: Импорт модулей на платформах без учёта регистра

В некоторых операционных системах файловые системы нечувствительны к регистру, в первую очередь это MacOS и Windows; в таких системах невозможно различить имена файлов `FILE.PY` и `file.py`, хотя они и хранят исходный регистр имени (они также сохраняют регистр).

В Python 2.1 оператор [`import`](https://python-all.ru/3.1/reference/simple_stmts.html#import) будет работать так, чтобы имитировать чувствительность к регистру на платформах, нечувствительных к регистру. Теперь Python по умолчанию будет искать первое совпадение с учётом регистра, вызывая [`ImportError`](https://python-all.ru/3.1/library/exceptions.html#ImportError), если такой файл не найден, поэтому `import file` не будет импортировать модуль с именем `FILE.PY`. Нечувствительное к регистру сопоставление можно запросить, установив переменную окружения [**PYTHONCASEOK**](https://python-all.ru/3.1/using/cmdline.html#envvar-PYTHONCASEOK) перед запуском интерпретатора Python.

## PEP 217: Интерактивный хук отображения

При интерактивной работе с интерпретатором Python вывод команд отображается с помощью встроенной функции [`repr()`](https://python-all.ru/3.1/library/functions.html#repr). В Python 2.1 переменной [`sys.displayhook()`](https://python-all.ru/3.1/library/sys.html#sys.displayhook) можно присвоить вызываемый объект, который будет вызван вместо [`repr()`](https://python-all.ru/3.1/library/functions.html#repr). Например, можно задать специальную функцию для красивого вывода:

```python
>>> # Создать рекурсивную структуру данных
... L = [1,2,3]
>>> L.append(L)
>>> L # Показать стандартный вывод Python
[1, 2, 3, [...]]
>>> # Использовать pprint.pprint() в качестве функции отображения
... import sys, pprint
>>> sys.displayhook = pprint.pprint
>>> L
[1, 2, 3,  <Recursion on list with id=135143996>]
>>>
```

> **См. также**
>
> **[**PEP 217**](https://python-all.ru/3.1/whatsnew/2.1.html) – Хук отображения для интерактивного использования**
>
> Автор и разработчик: Моше Задка.

## PEP 208: Новая модель приведения

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

Типы-расширения теперь могут устанавливать флаг типа `Py_TPFLAGS_CHECKTYPES` в своей структуре `PyTypeObject`, указывая, что они поддерживают новую модель приведения типов. В таких типах-расширениях функции числовых слотов больше не могут предполагать, что им будут переданы два аргумента одного типа; вместо этого им могут быть переданы два аргумента разных типов, и тогда они могут выполнять собственное внутреннее приведение. Если функции слота передан тип, который она не может обработать, она может указать на неудачу, вернув ссылку на синглтон `Py_NotImplemented`. Затем будут опробованы числовые функции другого типа; возможно, они смогут выполнить операцию; если другой тип также возвращает `Py_NotImplemented`, то будет возбуждено исключение [`TypeError`](https://python-all.ru/3.1/library/exceptions.html#TypeError). Числовые методы, написанные на Python, также могут возвращать `Py_NotImplemented`, заставляя интерпретатор действовать так, как будто метод не существует (возможно, будет возбуждено [`TypeError`](https://python-all.ru/3.1/library/exceptions.html#TypeError), возможно, будут опробованы числовые методы другого объекта).

> **См. также**
>
> **[**PEP 208**](https://python-all.ru/3.1/whatsnew/2.1.html) – Переработка модели приведения**
>
> Автор и разработчик: Нил Шеменауэр, на основе более ранней работы Марка-Андре Лембурга. Прочтите это, чтобы понять тонкости обработки числовых операций на уровне C.

## PEP 241: Метаданные в пакетах Python

Частая жалоба пользователей Python – отсутствие единого каталога всех существующих модулей Python. Хранилища Парнаса Т. Миддлтона ([http://www.vex.net/parnassus/](https://python-all.ru/3.1/whatsnew/2.1.html)) – крупнейший каталог модулей Python, но регистрация программного обеспечения в Хранилищах необязательна, и многие не утруждают себя этим.

В качестве первого небольшого шага к решению проблемы программное обеспечение Python, упакованное с помощью команды Distutils **sdist**, будет содержать файл с именем `PKG-INFO`, содержащий информацию о пакете, такую как его имя, версия и автор (метаданные в терминологии каталогизации). PEP 241 содержит полный список полей, которые могут присутствовать в файле `PKG-INFO`. Поскольку люди начали упаковывать своё программное обеспечение с помощью Python 2.1, всё больше пакетов будут включать метаданные, что позволит создавать автоматизированные системы каталогизации и экспериментировать с ними. На основе полученного опыта, возможно, удастся разработать действительно хороший каталог, а затем добавить поддержку для него в Python 2.2. Например, команды Distutils **sdist** и **bdist\_\*** могли бы поддерживать опцию *upload*, которая автоматически загружает пакет на сервер каталога.

Можно начать создавать пакеты, содержащие `PKG-INFO`, даже если вы не используете Python 2.1, поскольку новый выпуск Distutils будет подготовлен для пользователей более ранних версий Python. Версия 1.0.2 Distutils включает изменения, описанные в PEP 241, а также различные исправления и улучшения. Он будет доступен на Distutils SIG по адресу [http://www.python.org/sigs/distutils-sig/](https://python-all.ru/3.1/whatsnew/2.1.html).

> **См. также**
>
> **[**PEP 241**](https://python-all.ru/3.1/whatsnew/2.1.html) – Метаданные для пакетов программного обеспечения Python**
>
> Автор и разработчик: Э.М. Кухлинг.
>
> **[**PEP 243**](https://python-all.ru/3.1/whatsnew/2.1.html) – Механизм загрузки в репозиторий модулей**
>
> Автор: Шон Райфшнайдер. В этом черновике PEP описывается предлагаемый механизм загрузки пакетов Python на центральный сервер.

## Новые и улучшенные модули

- Ка-Пинг Йи предоставил два новых модуля: `inspect.py` – модуль для получения информации о работающем коде Python, и `pydoc.py` – модуль для интерактивного преобразования docstrings в HTML или текст. В качестве бонуса, `Tools/scripts/pydoc`, который теперь устанавливается автоматически, использует `pydoc.py` для отображения документации по имени модуля, пакета или класса Python. Например, `pydoc xml.dom` выводит следующее:

  ```python
  Python Library Documentation: package xml.dom in xml

  NAME
      xml.dom - W3C Document Object Model implementation for Python.

  FILE
      /usr/local/lib/python2.1/xml/dom/__init__.pyc

  DESCRIPTION
      The Python mapping of the Document Object Model is documented in the
      Python Library Reference in the section on the xml.dom package.

      This package contains the following modules:
        ...
  ```

  `pydoc` также включает интерактивный браузер справки на основе Tk. `pydoc` быстро вызывает привыкание; попробуйте!
- В стандартную библиотеку были добавлены два модуля для модульного тестирования. Модуль [`doctest`](https://python-all.ru/3.1/library/doctest.html#module-doctest), предоставленный Тимом Питерсом, предоставляет фреймворк для тестирования, основанный на запуске встроенных примеров в docstrings и сравнении результатов с ожидаемым выводом. PyUnit, предоставленный Стивом Пёрселлом, – это фреймворк модульного тестирования, вдохновлённый JUnit, который, в свою очередь, является адаптацией фреймворка тестирования Smalltalk Кента Бека. См. [http://pyunit.sourceforge.net/](https://python-all.ru/3.1/whatsnew/2.1.html) для получения дополнительной информации о PyUnit.
- Модуль [`difflib`](https://python-all.ru/3.1/library/difflib.html#module-difflib) содержит класс `SequenceMatcher`, который сравнивает две последовательности и вычисляет изменения, необходимые для преобразования одной последовательности в другую. Например, этот модуль можно использовать для написания инструмента, похожего на программу Unix **diff**, и на самом деле пример программы `Tools/scripts/ndiff.py` демонстрирует, как написать такой скрипт.
- [`curses.panel`](https://python-all.ru/3.1/library/curses.panel.html#module-curses.panel) – обёртка для библиотеки panel, входящей в состав ncurses и SYSV curses, был предоставлен Томасом Геллекюмом. Библиотека panel предоставляет окна с дополнительной возможностью глубины. Окна можно перемещать выше или ниже в порядке глубины, а библиотека panel определяет, где панели перекрываются и какие части видимы.
- Пакет PyXML прошёл через несколько релизов после Python 2.0, и Python 2.1 включает обновлённую версию пакета `xml`. Среди заметных изменений – поддержка Expat 1.2 и более поздних версий, возможность для парсеров Expat обрабатывать файлы в любой кодировке, поддерживаемой Python, и различные исправления ошибок для SAX, DOM и модуля `minidom`.
- Пинг также предоставил ещё один перехватчик для обработки необработанных исключений. [`sys.excepthook()`](https://python-all.ru/3.1/library/sys.html#sys.excepthook) можно установить в вызываемый объект. Когда исключение не перехвачено ни одним блоком [`try`](https://python-all.ru/3.1/reference/compound_stmts.html#try)...[`except`](https://python-all.ru/3.1/reference/compound_stmts.html#except), исключение будет передано в [`sys.excepthook()`](https://python-all.ru/3.1/library/sys.html#sys.excepthook), который может делать с ним что угодно. На Девятой конференции Python Пинг продемонстрировал применение этого перехватчика: вывод расширенной трассировки, которая включает не только стек вызовов, но также аргументы функций и локальные переменные для каждого кадра.
- Различные функции в модуле [`time`](https://python-all.ru/3.1/library/time.html#module-time), такие как `asctime()` и `localtime()`, требуют аргумент с плавающей запятой, содержащий время в секундах с начала эпохи. Наиболее частое использование этих функций – работа с текущим временем, поэтому аргумент с плавающей запятой сделали необязательным; если значение не указано, будет использоваться текущее время. Например, записи в файлах журнала обычно нуждаются в строке, содержащей текущее время; в Python 2.1, `time.asctime()` можно использовать вместо более длинного `time.asctime(time.localtime(time.time()))`, который требовался раньше.

  Это изменение было предложено и реализовано Томасом Воутерсом (Thomas Wouters).
- Модуль [`ftplib`](https://python-all.ru/3.1/library/ftplib.html#module-ftplib) теперь по умолчанию загружает файлы в пассивном режиме, поскольку пассивный режим с большей вероятностью работает из-за брандмауэра. Этот запрос поступил из системы отслеживания ошибок Debian, так как другие пакеты Debian используют [`ftplib`](https://python-all.ru/3.1/library/ftplib.html#module-ftplib) для загрузки файлов и затем не работают из-за брандмауэра. Вряд ли это вызовет проблемы у кого-либо, потому что Netscape по умолчанию использует пассивный режим, и мало кто жалуется, но если пассивный режим не подходит для вашего приложения или сетевой конфигурации, вызовите `set_pasv(0)()` на объектах FTP, чтобы отключить пассивный режим.
- В модуль [`socket`](https://python-all.ru/3.1/library/socket.html#module-socket) добавлена поддержка низкоуровневого доступа к сокетам; предоставлено Грантом Эдвардсом.
- Модуль [`pstats`](https://python-all.ru/3.1/library/profile.html#module-pstats) теперь содержит простой интерактивный обозреватель статистики для отображения профилей времени выполнения программ Python; запускается при выполнении модуля как скрипта. Предоставлено Эриком С. Рэймондом.
- Новая зависящая от реализации функция `sys._getframe([depth])()` добавлена для возврата заданного объекта фрейма из текущего стека вызовов. [`sys._getframe()`](https://python-all.ru/3.1/library/sys.html#sys._getframe) возвращает фрейм на вершине стека вызовов; если передан необязательный целочисленный аргумент *depth*, функция возвращает фрейм, находящийся на *depth* вызовов ниже вершины стека. Например, `sys._getframe(1)` возвращает объект фрейма вызывающей стороны.

  Эта функция присутствует только в CPython, но не в Jython или .NET-реализации. Используйте её для отладки и воздержитесь от использования в рабочем коде.

## Другие изменения и исправления

Из-за более короткого цикла релизов в Python 2.1 было сделано относительно немного мелких изменений. Поиск по журналам изменений CVS показывает 117 применённых патчей и 136 исправленных ошибок; обе цифры, вероятно, занижены. Некоторые из наиболее заметных изменений:

- Теперь опционально доступен специализированный распределитель объектов, который должен быть быстрее системного `malloc()` и иметь меньшие накладные расходы памяти. Распределитель использует функцию C `malloc()` для получения больших пулов памяти, а затем удовлетворяет более мелкие запросы памяти из этих пулов. Его можно включить, передав опцию *--with-pymalloc* скрипту **configure**; подробности реализации см. в `Objects/obmalloc.c`.

  Авторам модулей расширения C следует тестировать свой код с включённым распределителем объектов, потому что некорректный код может привести к сбоям и дампу памяти во время выполнения. В C API Python есть множество функций выделения памяти, которые ранее были просто псевдонимами для `malloc()` и `free()` из библиотеки C, то есть если случайно вызвать несоответствующие функции, ошибка не была бы заметна. Когда распределитель объектов включён, эти функции больше не являются псевдонимами `malloc()` и `free()`, и вызов неправильной функции для освобождения памяти приведёт к дампу памяти. Например, если память была выделена с помощью [`PyMem_New()`](https://python-all.ru/3.1/c-api/memory.html#PyMem_New), её нужно освобождать через [`PyMem_Del()`](https://python-all.ru/3.1/c-api/memory.html#PyMem_Del), а не через `free()`. Некоторые модули, входящие в состав Python, столкнулись с этой проблемой и были исправлены; несомненно, есть и другие сторонние модули, у которых будет та же проблема.

  Аллокатор объектов был предоставлен Владимиром Марангозовым (Vladimir Marangozov).
- Скорость построчного файлового ввода-вывода была улучшена, потому что пользователи часто жалуются на её недостаток, и потому что её часто использовали как наивный тест производительности. Поэтому метод `readline()` файловых объектов был переписан, чтобы стать намного быстрее. Точное ускорение будет варьироваться от платформы к платформе в зависимости от того, насколько медленной была функция `getc()` из библиотеки C, но составляет около 66% и потенциально может быть намного больше в некоторых операционных системах. Тим Питерс выполнил большую часть тестирования и написания кода для этого изменения, мотивированный обсуждением в comp.lang.python.

  Также был добавлен новый метод для файловых объектов, предоставленный Джеффом Эплером. Новый метод `xreadlines()` похож на существующую встроенную функцию `xrange()`. `xreadlines()` возвращает непрозрачный объект-последовательность, который поддерживает только итерацию, считывая одну строку на каждой итерации, но не загружая весь файл в память, как это делает существующий метод `readlines()`. Используется он так:

  ```python
  for line in sys.stdin.xreadlines():
      # ... сделать что-то для каждой строки ...
      ...
  ```

  Более полное обсуждение изменений в построчном вводе-выводе можно найти в сводке python-dev за 1–15 января 2001 года по адресу [http://www.python.org/dev/summary/2001-01-1/](https://python-all.ru/3.1/whatsnew/2.1.html).
- В словари добавлен новый метод `popitem()`, позволяющий итеративно просматривать содержимое словаря с разрушением; это может быть быстрее для больших словарей, поскольку не нужно создавать список, содержащий все ключи или значения. `D.popitem()` удаляет случайную пару `(key, value)` из словаря `D` и возвращает её в виде кортежа из двух элементов. Этот метод в основном реализован Тимом Питерсом и Гвидо ван Россумом после предложения и предварительного патча от Моше Задки.
- Теперь модули могут управлять тем, какие имена импортируются при использовании `from module import *`, путём определения атрибута `__all__`, содержащего список имён, которые будут импортированы. Одна из частых жалоб: если модуль импортирует другие модули, такие как [`sys`](https://python-all.ru/3.1/library/sys.html#module-sys) или [`string`](https://python-all.ru/3.1/library/string.html#module-string), то `from module import *` добавит их в пространство имён импортирующего модуля. Чтобы это исправить, просто перечислите публичные имена в `__all__`:

  ```python
  # Перечислить публичные имена
  __all__ = ['Database', 'open']
  ```

  Более строгая версия этого патча была впервые предложена и реализована Беном Вольфсоном (Ben Wolfson), но после обсуждения в python-dev была принята более мягкая окончательная версия.
- Applying [`repr()`](https://python-all.ru/3.1/library/functions.html#repr) to strings previously used octal escapes for non-printable characters; for example, a newline was `'\012'`. This was a vestigial trace of Python’s C ancestry, but today octal is of very little practical use. Ka-Ping Yee suggested using hex escapes instead of octal ones, and using the `\n`, `\t`, `\r` escapes for the appropriate characters, and implemented this new formatting.
- Синтаксические ошибки, обнаруженные во время компиляции, теперь могут вызывать исключения, содержащие имя файла и номер строки ошибки – приятный побочный эффект реорганизации компилятора, выполненной Джереми Хилтоном (Jeremy Hylton).
- Расширения на C, которые импортируют другие модули, были изменены для использования [`PyImport_ImportModule()`](https://python-all.ru/3.1/c-api/import.html#PyImport_ImportModule), что означает, что они будут использовать любые установленные перехватчики импорта. Это также рекомендуется для сторонних расширений, которым нужно импортировать какой-либо другой модуль из кода на C.
- Размер базы данных символов Unicode был уменьшен ещё на 340K благодаря Фредрику Лунду (Fredrik Lundh).
- Были добавлены новые порты: MacOS X (Стивен Маевски), Cygwin (Джейсон Тишлер), RISCOS (Дитмар Швертбергер), Unixware 7 (Билли Дж. Алли).

А также обычный список мелких исправлений ошибок, небольших утечек памяти, правок docstring и других доработок, слишком длинный, чтобы перечислять; если интересно, смотрите полные подробности в журналах CVS.

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

Автор хотел бы поблагодарить следующих людей за предложения по различным черновикам этой статьи: Грэм Кросс (Graeme Cross), Дэвид Гуджер (David Goodger), Джей Грейвз (Jay Graves), Майкл Хадсон (Michael Hudson), Марк-Андре Лембург (Marc-André Lemburg), Фредрик Лунд (Fredrik Lundh), Нил Шеменауэр (Neil Schemenauer), Томас Воутерс (Thomas Wouters).
