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

---

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

В этой статье описываются новые возможности Python 3.3 по сравнению с версией 3.2. Python 3.3 был выпущен 29 сентября 2012 года. Полные сведения приведены в [журнале изменений](https://python-all.ru/3.3/whatsnew/changelog.html).

> **См. также**
>
> [**PEP 398**](https://python-all.ru/3.9/whatsnew/3.3.html) – График выпуска Python 3.3

## Итоги – основные изменения

Новые синтаксические возможности:

- Новое выражение `yield from` для [делегирования генератору](https://python-all.ru/3.9/whatsnew/3.3.html#pep-380).
- Синтаксис `u'unicode'` снова разрешён для объектов [`str`](https://python-all.ru/3.9/library/stdtypes.html#str).

Новые модули библиотеки:

- [`faulthandler`](https://python-all.ru/3.9/library/faulthandler.html#module-faulthandler) (помогает отлаживать низкоуровневые сбои)
- [`ipaddress`](https://python-all.ru/3.9/library/ipaddress.html#module-ipaddress) (высокоуровневые объекты для представления IP-адресов и масок)
- [`lzma`](https://python-all.ru/3.9/library/lzma.html#module-lzma) (сжатие данных с использованием алгоритма XZ/LZMA)
- [`unittest.mock`](https://python-all.ru/3.9/library/unittest.mock.html#module-unittest.mock) (замена частей тестируемой системы mock-объектами)
- [`venv`](https://python-all.ru/3.9/library/venv.html#module-venv) ([виртуальные окружения](https://python-all.ru/3.9/whatsnew/3.3.html#pep-405) Python, как в популярном `virtualenv` пакете)

Новые встроенные возможности:

- Переработанная [иерархия исключений ввода-вывода](https://python-all.ru/3.9/whatsnew/3.3.html#pep-3151).

Улучшения реализации:

- Переписан [механизм импорта](https://python-all.ru/3.9/whatsnew/3.3.html#importlib) на основе [`importlib`](https://python-all.ru/3.9/library/importlib.html#module-importlib).
- Более компактные [строки Unicode](https://python-all.ru/3.9/whatsnew/3.3.html#pep-393).
- Более компактные [словари атрибутов](https://python-all.ru/3.9/whatsnew/3.3.html#pep-412).

Значительно улучшенные модули библиотеки:

- C-акселератор для модуля [decimal](https://python-all.ru/3.9/whatsnew/3.3.html#new-decimal).
- Улучшенная обработка Unicode в модуле [email](https://python-all.ru/3.9/whatsnew/3.3.html#new-email) ([предварительный](https://python-all.ru/3.9/glossary.html#term-provisional-package)).

Улучшения в области безопасности:

- Рандомизация хэшей включена по умолчанию.

Читайте далее, чтобы ознакомиться с полным списком изменений, значимых для пользователя.

## PEP 405: Виртуальные окружения

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

Данный PEP добавляет модуль [`venv`](https://python-all.ru/3.9/library/venv.html#module-venv) для программного доступа и скрипт `pyvenv` для доступа через командную строку и администрирования. Интерпретатор Python проверяет наличие `pyvenv.cfg`, файла, существование которого указывает на корень дерева каталогов виртуального окружения.

> **См. также**
>
> **[**PEP 405**](https://python-all.ru/3.9/whatsnew/3.3.html) – Виртуальные окружения Python**
>
> PEP написан Carl Meyer; реализация Carl Meyer и Vinay Sajip

## PEP 420: Неявные пакеты пространства имён

Встроенная поддержка каталогов пакетов, которые не требуют `__init__.py` файлов-маркеров и могут автоматически охватывать несколько сегментов пути (вдохновлена различными сторонними подходами к пакетам пространств имён, как описано в [**PEP 420**](https://python-all.ru/3.9/whatsnew/3.3.html))

> **См. также**
>
> **[**PEP 420**](https://python-all.ru/3.9/whatsnew/3.3.html) – Неявные пакеты пространства имён**
>
> PEP написан Eric V. Smith; реализация Eric V. Smith и Barry Warsaw

## PEP 3118: Новая реализация memoryview и документация протокола буфера

Реализация [**PEP 3118**](https://python-all.ru/3.9/whatsnew/3.3.html) была значительно улучшена.

Новая реализация memoryview полностью устраняет все проблемы владения и времени жизни динамически выделяемых полей в структуре Py\_buffer, которые приводили к многочисленным сообщениям о сбоях. Кроме того, исправлены несколько функций, которые приводили к сбоям или возвращали неверные результаты для несплошных или многомерных входных данных.

Объект memoryview теперь имеет совместимый с PEP 3118 метод getbufferproc(), который проверяет тип запроса потребителя. Добавлено множество новых возможностей, большинство из которых работают в полной общности для несплошных массивов и массивов с под-смещениями.

Документация была обновлена, чётко разъясняя обязанности как экспортёров, так и потребителей. Флаги запросов буфера сгруппированы в базовые и составные. Объясняется расположение в памяти несплошных и многомерных массивов в стиле NumPy.

### Возможности

- Теперь поддерживаются все нативные односимвольные спецификаторы формата в синтаксисе модуля struct (с возможным префиксом '@').
- С некоторыми ограничениями метод cast() позволяет изменять формат и форму C-сплошных массивов.
- Поддерживаются многомерные представления в виде списков для любого типа массива.
- Поддерживаются многомерные сравнения для любого типа массива.
- Одномерные представления памяти (memoryview) хешируемых (только для чтения) типов с форматами B, b или c теперь хешируемы. (Предложено Antoine Pitrou в [bpo-13411](https://python-all.ru/3.9/whatsnew/3.3.html).)
- Поддерживается произвольная нарезка одномерных массивов любого типа. Например, теперь можно обратить memoryview за O(1), используя отрицательный шаг.

### Изменения API

- Максимальное количество измерений официально ограничено 64.
- Представление пустых shape, strides и suboffsets теперь представляет собой пустой кортеж вместо `None`.
- Доступ к элементу memoryview с форматом 'B' (беззнаковые байты) теперь возвращает целое число (в соответствии с синтаксисом модуля struct). Чтобы вернуть объект bytes, представление должно быть сначала приведено к 'c'.
- Сравнения memoryview теперь используют логическую структуру операндов и сравнивают все элементы массива по значению. Поддерживаются все строки формата в синтаксисе модуля struct. Представления с нераспознанными строками формата по-прежнему допускаются, но всегда будут сравниваться как неравные, независимо от содержимого представления.
- Дополнительные изменения см. в разделе [Изменения сборки и C API](https://python-all.ru/3.9/whatsnew/3.3.html#build-and-c-api-changes) и [Перенос кода на C](https://python-all.ru/3.9/whatsnew/3.3.html#porting-c-code).

(Автор: Stefan Krah в [bpo-10181](https://python-all.ru/3.9/whatsnew/3.3.html).)

> **См. также**
>
> [**PEP 3118**](https://python-all.ru/3.9/whatsnew/3.3.html) - Пересмотр протокола буфера

## PEP 393: Гибкое представление строк

Тип строки Unicode изменён для поддержки нескольких внутренних представлений в зависимости от символа с наибольшим порядковым номером Unicode (1, 2 или 4 байта) в представляемой строке. Это позволяет обеспечить эффективное по памяти представление в распространённых случаях, но даёт доступ к полному UCS-4 во всех системах. Для совместимости с существующими API несколько представлений могут существовать параллельно; со временем эта совместимость должна быть прекращена.

Со стороны Python у этого изменения не должно быть недостатков.

Со стороны C API [**PEP 393**](https://python-all.ru/3.9/whatsnew/3.3.html) полностью обратно совместим. Устаревший API должен оставаться доступным как минимум пять лет. Приложения, использующие устаревший API, не получат полной выгоды от сокращения памяти или, что хуже, могут использовать немного больше памяти, поскольку Python может поддерживать две версии каждой строки (в устаревшем формате и в новом эффективном хранилище).

### Функциональность

Изменения, введённые [**PEP 393**](https://python-all.ru/3.9/whatsnew/3.3.html), заключаются в следующем:

- Python теперь всегда поддерживает полный диапазон кодовых точек Unicode, включая не-BMP (т.е. от `U+0000` до `U+10FFFF`). Различие между узкой и широкой сборками больше не существует, и Python теперь ведёт себя как широкая сборка, даже под Windows.
- С исчезновением узких сборок также были исправлены проблемы, характерные для узких сборок, например:

  - [`len()`](https://python-all.ru/3.9/library/functions.html#len) теперь всегда возвращает 1 для не-BMP символов, поэтому `len('\U0010FFFF') == 1`;
  - суррогатные пары не рекомбинируются в строковых литералах, поэтому `'\uDBFF\uDFFF' != '\U0010FFFF'`;
  - индексирование или нарезка не-BMP символов возвращает ожидаемое значение, поэтому `'\U0010FFFF'[0]` теперь возвращает `'\U0010FFFF'`, а не `'\uDBFF'`;
  - все остальные функции в стандартной библиотеке теперь корректно обрабатывают не-BMP кодовые точки.
- Значение [`sys.maxunicode`](https://python-all.ru/3.9/library/sys.html#sys.maxunicode) теперь всегда `1114111` (`0x10FFFF` в шестнадцатеричном виде). Функция `PyUnicode_GetMax()` по-прежнему возвращает либо `0xFFFF`, либо `0x10FFFF` для обратной совместимости, и её не следует использовать с новым Unicode API (см. [bpo-13054](https://python-all.ru/3.9/whatsnew/3.3.html)).
- Флаг `./configure` `--with-wide-unicode` удалён.

### Производительность и использование ресурсов

Хранение строк Unicode теперь зависит от наибольшей кодовой точки в строке:

- строки чистого ASCII и Latin1 (`U+0000-U+00FF`) используют 1 байт на кодовую точку;
- строки BMP (`U+0000-U+FFFF`) используют 2 байта на кодовую точку;
- строки не-BMP (`U+10000-U+10FFFF`) используют 4 байта на кодовую точку.

В итоге для большинства приложений потребление памяти для хранения строк должно значительно уменьшиться – особенно по сравнению с прежними сборками с широкими символами – поскольку во многих случаях строки будут чистыми ASCII daже в международных контекстах (потому что многие строки хранят неязыковые данные, такие как фрагменты XML, заголовки HTTP, данные в JSON и т.д.). Мы также надеемся, что по тем же причинам это повысит эффективность кэша ЦП в нетривиальных приложениях. Потребление памяти в Python 3.3 в два-три раза меньше, чем в Python 3.2, и немного лучше, чем в Python 2.7, согласно бенчмарку Django (подробности см. в PEP).

> **См. также**
>
> **[**PEP 393**](https://python-all.ru/3.9/whatsnew/3.3.html) – Гибкое представление строк**
>
> PEP написан Мартином фон Лёвисом; реализация – Торстен Беккер и Мартин фон Лёвис.

## PEP 397: Средство запуска Python для Windows

Установщик Python 3.3 для Windows теперь включает приложение `py`-запускатор, которое можно использовать для запуска приложений Python независимо от их версии.

Этот запускатор вызывается неявно при двойном щелчке по файлам `*.py`. Если в системе установлена только одна версия Python, для запуска файла будет использована она. Если установлено несколько версий, по умолчанию используется самая новая, но это можно переопределить, включив в скрипт Python строку shebang в стиле Unix.

Запускатор можно также использовать явно из командной строки как приложение `py`. Запуск `py` подчиняется тем же правилам выбора версии, что и неявный запуск скриптов, но можно выбрать более конкретную версию, передав соответствующие аргументы (например, `-3` для запроса Python 3, если также установлен Python 2, или `-2.6` для запроса более ранней версии Python, если установлена более новая).

В дополнение к запускатору установщик Windows теперь включает опцию добавления только что установленного Python в системную переменную PATH. (Предложено Брайаном Кертином в [bpo-3561](https://python-all.ru/3.9/whatsnew/3.3.html).)

> **См. также**
>
> **[**PEP 397**](https://python-all.ru/3.9/whatsnew/3.3.html) – Средство запуска Python для Windows**
>
> PEP написан Марком Хаммондом и Мартином в. Лёвисом; реализация – Винай Саджип.
>
> Документация по средству запуска: [Python Launcher for Windows](https://python-all.ru/3.9/using/windows.html#launcher)
>
> Изменение PATH установщиком: [Finding the Python executable](https://python-all.ru/3.9/using/windows.html#windows-path-mod)

## PEP 3151: Переработка иерархии исключений ОС и ввода-вывода

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

Больше не нужно беспокоиться о выборе подходящего типа исключения среди [`OSError`](https://python-all.ru/3.9/library/exceptions.html#OSError), [`IOError`](https://python-all.ru/3.9/library/exceptions.html#IOError), [`EnvironmentError`](https://python-all.ru/3.9/library/exceptions.html#EnvironmentError), [`WindowsError`](https://python-all.ru/3.9/library/exceptions.html#WindowsError), `mmap.error`, [`socket.error`](https://python-all.ru/3.9/library/socket.html#socket.error) или [`select.error`](https://python-all.ru/3.9/library/select.html#select.error). Все эти типы исключений теперь – один: [`OSError`](https://python-all.ru/3.9/library/exceptions.html#OSError). Остальные имена сохранены как псевдонимы для совместимости.

Кроме того, теперь легче перехватить конкретную ошибочную ситуацию. Вместо проверки атрибута `errno` (или `args[0]`) на наличие определённой константы из модуля [`errno`](https://python-all.ru/3.9/library/errno.html#module-errno) можно перехватить соответствующий подкласс [`OSError`](https://python-all.ru/3.9/library/exceptions.html#OSError). Доступны следующие подклассы:

- [`BlockingIOError`](https://python-all.ru/3.9/library/exceptions.html#BlockingIOError)
- [`ChildProcessError`](https://python-all.ru/3.9/library/exceptions.html#ChildProcessError)
- [`ConnectionError`](https://python-all.ru/3.9/library/exceptions.html#ConnectionError)
- [`FileExistsError`](https://python-all.ru/3.9/library/exceptions.html#FileExistsError)
- [`FileNotFoundError`](https://python-all.ru/3.9/library/exceptions.html#FileNotFoundError)
- [`InterruptedError`](https://python-all.ru/3.9/library/exceptions.html#InterruptedError)
- [`IsADirectoryError`](https://python-all.ru/3.9/library/exceptions.html#IsADirectoryError)
- [`NotADirectoryError`](https://python-all.ru/3.9/library/exceptions.html#NotADirectoryError)
- [`PermissionError`](https://python-all.ru/3.9/library/exceptions.html#PermissionError)
- [`ProcessLookupError`](https://python-all.ru/3.9/library/exceptions.html#ProcessLookupError)
- [`TimeoutError`](https://python-all.ru/3.9/library/exceptions.html#TimeoutError)

А сам [`ConnectionError`](https://python-all.ru/3.9/library/exceptions.html#ConnectionError) имеет более детализированные подклассы:

- [`BrokenPipeError`](https://python-all.ru/3.9/library/exceptions.html#BrokenPipeError)
- [`ConnectionAbortedError`](https://python-all.ru/3.9/library/exceptions.html#ConnectionAbortedError)
- [`ConnectionRefusedError`](https://python-all.ru/3.9/library/exceptions.html#ConnectionRefusedError)
- [`ConnectionResetError`](https://python-all.ru/3.9/library/exceptions.html#ConnectionResetError)

Благодаря новым исключениям теперь можно избежать типичных применений [`errno`](https://python-all.ru/3.9/library/errno.html#module-errno). Например, следующий код, написанный для Python 3.2:

```python
from errno import ENOENT, EACCES, EPERM

try:
    with open("document.txt") as f:
        content = f.read()
except IOError as err:
    if err.errno == ENOENT:
        print("document.txt file is missing")
    elif err.errno in (EACCES, EPERM):
        print("You are not allowed to read document.txt")
    else:
        raise
```

теперь можно написать без импорта [`errno`](https://python-all.ru/3.9/library/errno.html#module-errno) и без ручной проверки атрибутов исключений:

```python
try:
    with open("document.txt") as f:
        content = f.read()
except FileNotFoundError:
    print("document.txt file is missing")
except PermissionError:
    print("You are not allowed to read document.txt")
```

> **См. также**
>
> **[**PEP 3151**](https://python-all.ru/3.9/whatsnew/3.3.html) – Переработка иерархии исключений ОС и ввода-вывода**
>
> PEP написан и реализован Антуаном Питру

## PEP 380: Синтаксис делегирования подгенератору

PEP 380 добавляет выражение `yield from`, позволяя [генератору](https://python-all.ru/3.9/glossary.html#term-generator) делегировать часть своих операций другому генератору. Это позволяет вынести участок кода, содержащий [`yield`](https://python-all.ru/3.9/reference/simple_stmts.html#yield), и поместить его в другой генератор. Кроме того, подгенератору разрешается возвращать значение, и это значение становится доступным делегирующему генератору.

Хотя изначально предназначено для делегирования подгенератору, выражение `yield from` на самом деле позволяет делегирование произвольным под-итераторам.

Для простых итераторов `yield from iterable` – это, по сути, сокращённая форма `for item in iterable: yield item`:

```python
>>> def g(x):
...     yield from range(x, 0, -1)
...     yield from range(x)
...
>>> list(g(5))
[5, 4, 3, 2, 1, 0, 1, 2, 3, 4]
```

Однако, в отличие от обычного цикла, `yield from` позволяет подгенераторам напрямую получать из вызывающей области видимости значения, переданные в генератор, и исключения, проброшенные в него, а также возвращать конечное значение внешнему генератору:

```python
>>> def accumulate():
...     tally = 0
...     while 1:
...         next = yield
...         if next is None:
...             return tally
...         tally += next
...
>>> def gather_tallies(tallies):
...     while 1:
...         tally = yield from accumulate()
...         tallies.append(tally)
...
>>> tallies = []
>>> acc = gather_tallies(tallies)
>>> next(acc)  # Убедиться, что аккумулятор готов к приёму значений
>>> for i in range(4):
...     acc.send(i)
...
>>> acc.send(None)  # Завершить первый подсчёт
>>> for i in range(5):
...     acc.send(i)
...
>>> acc.send(None)  # Завершить второй подсчёт
>>> tallies
[6, 10]
```

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

> **См. также**
>
> **[**PEP 380**](https://python-all.ru/3.9/whatsnew/3.3.html) - Syntax for Delegating to a Subgenerator**
>
> PEP написан Грегом Юингом; реализовано Грегом Юингом, включено в версию 3.3 Рено Бланшем, Райаном Келли и Ником Когланом; документация – Збигнев Енджеевски-Шмек и Ник Коглан

## PEP 409: Подавление контекста исключения

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

```python
>>> class D:
...     def __init__(self, extra):
...         self._extra_attributes = extra
...     def __getattr__(self, attr):
...         try:
...             return self._extra_attributes[attr]
...         except KeyError:
...             raise AttributeError(attr) from None
...
>>> D({}).x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 8, in __getattr__
AttributeError: x
```

Без суффикса `from None` для подавления причины исходное исключение по умолчанию отображалось бы:

```python
>>> class C:
...     def __init__(self, extra):
...         self._extra_attributes = extra
...     def __getattr__(self, attr):
...         try:
...             return self._extra_attributes[attr]
...         except KeyError:
...             raise AttributeError(attr)
...
>>> C({}).x
Traceback (most recent call last):
  File "<stdin>", line 6, in __getattr__
KeyError: 'x'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 8, in __getattr__
AttributeError: x
```

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

```python
>>> try:
...     D({}).x
... except AttributeError as exc:
...     print(repr(exc.__context__))
...
KeyError('x',)
```

> **См. также**
>
> **[**PEP 409**](https://python-all.ru/3.9/whatsnew/3.3.html) – Подавление контекста исключения**
>
> PEP написан Итаном Фурманом; реализован Итаном Фурманом и Ником Когланом.

## PEP 414: Явные литералы Unicode

Чтобы облегчить переход с Python 2 для приложений, работающих с Unicode, которые активно используют литералы Unicode, Python 3.3 снова поддерживает префикс «`u`» для строковых литералов. В Python 3 этот префикс не имеет семантического значения, он предоставлен исключительно для уменьшения количества чисто механических изменений при миграции на Python 3, позволяя разработчикам сосредоточиться на более значительных семантических изменениях (таких как более строгое разделение двоичных и текстовых данных по умолчанию).

> **См. также**
>
> **[**PEP 414**](https://python-all.ru/3.9/whatsnew/3.3.html) – Явные литералы Unicode**
>
> PEP написан Армином Ронахером.

## PEP 3155: Полное имя для классов и функций

У функций и объектов классов появился новый атрибут `__qualname__`, представляющий «путь» от верхнего уровня модуля до их определения. Для глобальных функций и классов он совпадает с `__name__`. Для остальных функций и классов он предоставляет более точные сведения о том, где они на самом деле были определены, и как к ним можно получить доступ из глобальной области видимости.

Пример с (несвязанными) методами:

```python
>>> class C:
...     def meth(self):
...         pass
>>> C.meth.__name__
'meth'
>>> C.meth.__qualname__
'C.meth'
```

Пример с вложенными классами:

```python
>>> class C:
...     class D:
...         def meth(self):
...             pass
...
>>> C.D.__name__
'D'
>>> C.D.__qualname__
'C.D'
>>> C.D.meth.__name__
'meth'
>>> C.D.meth.__qualname__
'C.D.meth'
```

Пример с вложенными функциями:

```python
>>> def outer():
...     def inner():
...         pass
...     return inner
...
>>> outer().__name__
'inner'
>>> outer().__qualname__
'outer.<locals>.inner'
```

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

```python
>>> str(C.D)
"<class '__main__.C.D'>"
>>> str(C.D.meth)
'<function C.D.meth at 0x7f46b9fe31e0>'
```

> **См. также**
>
> **[**PEP 3155**](https://python-all.ru/3.9/whatsnew/3.3.html) – Полное имя для классов и функций**
>
> PEP написан и реализован Antoine Pitrou.

## PEP 412: Словарь с разделением ключей

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

> **См. также**
>
> **[**PEP 412**](https://python-all.ru/3.9/whatsnew/3.3.html) – Словарь с разделением ключей**
>
> PEP написан и реализован Марком Шенноном.

## PEP 362: Объект сигнатуры функции

Новая функция [`inspect.signature()`](https://python-all.ru/3.9/library/inspect.html#inspect.signature) делает интроспекцию вызываемых объектов Python простой и понятной. Поддерживается широкий спектр вызываемых объектов: функции Python (декорированные или нет), классы и объекты [`functools.partial()`](https://python-all.ru/3.9/library/functools.html#functools.partial). Новые классы [`inspect.Signature`](https://python-all.ru/3.9/library/inspect.html#inspect.Signature), [`inspect.Parameter`](https://python-all.ru/3.9/library/inspect.html#inspect.Parameter) и [`inspect.BoundArguments`](https://python-all.ru/3.9/library/inspect.html#inspect.BoundArguments) содержат информацию о сигнатурах вызова, такую как аннотации, значения по умолчанию, виды параметров и связанные аргументы, что значительно упрощает написание декораторов и любого кода, который проверяет или изменяет сигнатуры вызова или аргументы.

> **См. также**
>
> **[**PEP 362**](https://python-all.ru/3.9/whatsnew/3.3.html): – Объект сигнатуры функции**
>
> PEP написан Бреттом Кэнноном, Юрием Селивановым, Ларри Хастингсом, Дживон Со; реализован Юрием Селивановым.

## PEP 421: Добавление sys.implementation

Новый атрибут модуля [`sys`](https://python-all.ru/3.9/library/sys.html#module-sys) раскрывает детали, специфичные для реализации текущего интерпретатора. Начальный набор атрибутов в [`sys.implementation`](https://python-all.ru/3.9/library/sys.html#sys.implementation): `name`, `version`, `hexversion` и `cache_tag`.

Цель `sys.implementation` – собрать в одном пространстве имён данные, специфичные для реализации, используемые стандартной библиотекой. Это позволяет разным реализациям Python гораздо проще использовать общую кодовую базу стандартной библиотеки. В начальном состоянии `sys.implementation` содержит лишь небольшую часть данных, специфичных для реализации. Со временем это соотношение будет меняться, чтобы сделать стандартную библиотеку более переносимой.

Одним из примеров улучшения переносимости стандартной библиотеки является `cache_tag`. Начиная с Python 3.3, `sys.implementation.cache_tag` используется [`importlib`](https://python-all.ru/3.9/library/importlib.html#module-importlib) для поддержки соответствия [**PEP 3147**](https://python-all.ru/3.9/whatsnew/3.3.html). Любая реализация Python, использующая `importlib` для своей встроенной системы импорта, может использовать `cache_tag` для управления поведением кэширования модулей.

### SimpleNamespace

Реализация `sys.implementation` также вводит новый тип в Python: [`types.SimpleNamespace`](https://python-all.ru/3.9/library/types.html#types.SimpleNamespace). В отличие от основанного на отображении пространства имён, такого как [`dict`](https://python-all.ru/3.9/library/stdtypes.html#dict), `SimpleNamespace` основано на атрибутах, как [`object`](https://python-all.ru/3.9/library/functions.html#object). Однако, в отличие от `object`, экземпляры `SimpleNamespace` доступны для записи. Это означает, что можно добавлять, удалять и изменять пространство имён через обычный доступ к атрибутам.

> **См. также**
>
> **[**PEP 421**](https://python-all.ru/3.9/whatsnew/3.3.html) – добавление sys.implementation**
>
> PEP написан и реализован Эриком Сноу.

## Использование importlib в качестве реализации импорта

[bpo-2377](https://python-all.ru/3.9/whatsnew/3.3.html) – замена \_\_import\_\_ на importlib.\_\_import\_\_ [bpo-13959](https://python-all.ru/3.9/whatsnew/3.3.html) – перереализация частей [`imp`](https://python-all.ru/3.9/library/imp.html#module-imp) на чистом Python [bpo-14605](https://python-all.ru/3.9/whatsnew/3.3.html) – сделать механизм импорта явным [bpo-14646](https://python-all.ru/3.9/whatsnew/3.3.html) – требование, чтобы загрузчики устанавливали \_\_loader\_\_ и \_\_package\_\_

Функция [`__import__()`](https://python-all.ru/3.9/library/functions.html#__import__) теперь работает на основе [`importlib.__import__()`](https://python-all.ru/3.9/library/importlib.html#importlib.__import__). Эта работа приводит к завершению «фазы 2» [**PEP 302**](https://python-all.ru/3.9/whatsnew/3.3.html). У этого изменения есть несколько преимуществ. Во-первых, оно позволило сделать больше механизмов, управляющих импортом, явными, а не неявными и скрытыми в коде на C. Также оно предоставляет единую реализацию для всех виртуальных машин Python, поддерживающих Python 3.3, помогая устранить любые отклонения в семантике импорта, зависящие от конкретной VM. И наконец, оно упрощает сопровождение импорта, позволяя развиваться в будущем.

Для обычного пользователя видимых изменений в семантике быть не должно. Для тех, чей код в настоящее время манипулирует импортом или вызывает import программно, возможные необходимые изменения в коде описаны в разделе [Перенос кода Python](https://python-all.ru/3.9/whatsnew/3.3.html#porting-python-code) этого документа.

### Новые API

Одним из больших преимуществ этой работы является раскрытие того, что участвует в обеспечении работы оператора import. Это означает, что различные импортёры, которые когда-то были неявными, теперь полностью раскрыты как часть пакета [`importlib`](https://python-all.ru/3.9/library/importlib.html#module-importlib).

Абстрактные базовые классы, определённые в [`importlib.abc`](https://python-all.ru/3.9/library/importlib.html#module-importlib.abc), были расширены, чтобы правильно разграничивать [искатели метапути](https://python-all.ru/3.9/glossary.html#term-meta-path-finder) и [искатели путевых записей](https://python-all.ru/3.9/glossary.html#term-path-entry-finder) путём введения [`importlib.abc.MetaPathFinder`](https://python-all.ru/3.9/library/importlib.html#importlib.abc.MetaPathFinder) и [`importlib.abc.PathEntryFinder`](https://python-all.ru/3.9/library/importlib.html#importlib.abc.PathEntryFinder) соответственно. Старый ABC [`importlib.abc.Finder`](https://python-all.ru/3.9/library/importlib.html#importlib.abc.Finder) теперь предоставляется только для обратной совместимости и не налагает никаких требований к методам.

В отношении искателей, [`importlib.machinery.FileFinder`](https://python-all.ru/3.9/library/importlib.html#importlib.machinery.FileFinder) раскрывает механизм, используемый для поиска исходных файлов и файлов байт-кода модуля. Ранее этот класс был неявным членом [`sys.path_hooks`](https://python-all.ru/3.9/library/sys.html#sys.path_hooks).

Для загрузчиков новый абстрактный базовый класс [`importlib.abc.FileLoader`](https://python-all.ru/3.9/library/importlib.html#importlib.abc.FileLoader) помогает написать загрузчик, использующий файловую систему в качестве механизма хранения кода модуля. Загрузчик для исходных файлов ([`importlib.machinery.SourceFileLoader`](https://python-all.ru/3.9/library/importlib.html#importlib.machinery.SourceFileLoader)), файлов байт-кода без исходников ([`importlib.machinery.SourcelessFileLoader`](https://python-all.ru/3.9/library/importlib.html#importlib.machinery.SourcelessFileLoader)) и модулей расширений ([`importlib.machinery.ExtensionFileLoader`](https://python-all.ru/3.9/library/importlib.html#importlib.machinery.ExtensionFileLoader)) теперь доступны для непосредственного использования.

[`ImportError`](https://python-all.ru/3.9/library/exceptions.html#ImportError) теперь имеет атрибуты `name` и `path`, которые устанавливаются, когда есть соответствующие данные для предоставления. Сообщение о неудачном импорте теперь также будет содержать полное имя модуля вместо только хвостовой части имени модуля.

Функция [`importlib.invalidate_caches()`](https://python-all.ru/3.9/library/importlib.html#importlib.invalidate_caches) теперь будет вызывать метод с тем же именем на всех искателях, кэшированных в [`sys.path_importer_cache`](https://python-all.ru/3.9/library/sys.html#sys.path_importer_cache), чтобы помочь очистить любое сохранённое состояние при необходимости.

### Видимые изменения

О возможных необходимых изменениях в коде см. раздел [Перенос кода Python](https://python-all.ru/3.9/whatsnew/3.3.html#porting-python-code).

Помимо расширения того, что [`importlib`](https://python-all.ru/3.9/library/importlib.html#module-importlib) теперь раскрывает, есть и другие видимые изменения в импорте. Самое большое из них – то, что [`sys.meta_path`](https://python-all.ru/3.9/library/sys.html#sys.meta_path) и [`sys.path_hooks`](https://python-all.ru/3.9/library/sys.html#sys.path_hooks) теперь хранят все искатели метапути и хуки путевых записей, используемые импортом. Ранее искатели были неявными и скрытыми в C-коде импорта, а не раскрытыми напрямую. Это означает, что теперь можно легко удалять или изменять порядок различных искателей в соответствии со своими потребностями.

Ещё одно изменение заключается в том, что все модули имеют атрибут `__loader__`, хранящий загрузчик, использованный для создания модуля. [**PEP 302**](https://python-all.ru/3.9/whatsnew/3.3.html) был обновлён, чтобы сделать этот атрибут обязательным для реализации загрузчиками, так что в будущем, после обновления сторонних загрузчиков, можно будет полагаться на существование этого атрибута. Однако до тех пор import устанавливает атрибут после загрузки модуля.

От загрузчиков также теперь ожидается установка атрибута `__package__` из [**PEP 366**](https://python-all.ru/3.9/whatsnew/3.3.html). Опять же, сам import уже устанавливает это на всех загрузчиках из [`importlib`](https://python-all.ru/3.9/library/importlib.html#module-importlib), и import сам устанавливает атрибут после загрузки.

`None` теперь вставляется в [`sys.path_importer_cache`](https://python-all.ru/3.9/library/sys.html#sys.path_importer_cache), когда ни один искатель не может быть найден в [`sys.path_hooks`](https://python-all.ru/3.9/library/sys.html#sys.path_hooks). Поскольку [`imp.NullImporter`](https://python-all.ru/3.9/library/imp.html#imp.NullImporter) не раскрывается напрямую в [`sys.path_hooks`](https://python-all.ru/3.9/library/sys.html#sys.path_hooks), на него больше нельзя полагаться как на всегда доступное значение, представляющее отсутствие найденного искателя.

Все остальные изменения относятся к семантическим изменениям, которые следует учитывать при обновлении кода для Python 3.3, и поэтому о них следует прочитать в разделе [Перенос кода Python](https://python-all.ru/3.9/whatsnew/3.3.html#porting-python-code) этого документа.

(Реализация – Бретт Кэннон)

## Прочие изменения языка

Некоторые небольшие изменения, внесённые в ядро языка Python:

- Добавлена поддержка псевдонимов имён Unicode и именованных последовательностей. Как [`unicodedata.lookup()`](https://python-all.ru/3.9/library/unicodedata.html#unicodedata.lookup), так и `'\N{...}'` теперь распознают псевдонимы имён, а [`unicodedata.lookup()`](https://python-all.ru/3.9/library/unicodedata.html#unicodedata.lookup) также распознаёт именованные последовательности.

  (Предложено Эцио Мелотти в [bpo-12753](https://python-all.ru/3.9/whatsnew/3.3.html).)
- База данных Unicode обновлена до версии UCD 6.1.0
- Сравнения на равенство объектов [`range()`](https://python-all.ru/3.9/library/stdtypes.html#range) теперь возвращают результат, отражающий равенство базовых последовательностей, порождённых этими объектами range. ([bpo-13201](https://python-all.ru/3.9/whatsnew/3.3.html))
- Методы `count()`, `find()`, `rfind()`, `index()` и `rindex()` объектов [`bytes`](https://python-all.ru/3.9/library/stdtypes.html#bytes) и [`bytearray`](https://python-all.ru/3.9/library/stdtypes.html#bytearray) теперь принимают целое число от 0 до 255 в качестве первого аргумента.

  (Предложено Петри Лехтиненом в [bpo-12170](https://python-all.ru/3.9/whatsnew/3.3.html).)
- Методы `rjust()`, `ljust()` и `center()` объектов [`bytes`](https://python-all.ru/3.9/library/stdtypes.html#bytes) и [`bytearray`](https://python-all.ru/3.9/library/stdtypes.html#bytearray) теперь принимают [`bytearray`](https://python-all.ru/3.9/library/stdtypes.html#bytearray) для аргумента `fill`. (Предложено Петри Лехтиненом в [bpo-12380](https://python-all.ru/3.9/whatsnew/3.3.html).)
- В [`list`](https://python-all.ru/3.9/library/stdtypes.html#list) и [`bytearray`](https://python-all.ru/3.9/library/stdtypes.html#bytearray) добавлены новые методы: `copy()` и `clear()` ([bpo-10516](https://python-all.ru/3.9/whatsnew/3.3.html)). Следовательно, [`MutableSequence`](https://python-all.ru/3.9/library/collections.abc.html#collections.abc.MutableSequence) теперь также определяет метод `clear()` ([bpo-11388](https://python-all.ru/3.9/whatsnew/3.3.html)).
- Сырые литералы байт теперь можно записывать как `rb"..."`, так и `br"..."`.

  (Добавлено Антуаном Питу в [bpo-13748](https://python-all.ru/3.9/whatsnew/3.3.html).)
- [`dict.setdefault()`](https://python-all.ru/3.9/library/stdtypes.html#dict.setdefault) теперь выполняет только один поиск заданного ключа, что делает его атомарным при использовании со встроенными типами.

  (Добавлено Филипом Грущинским в [bpo-13521](https://python-all.ru/3.9/whatsnew/3.3.html).)
- Сообщения об ошибках, которые выдаются, когда вызов функции не соответствует её сигнатуре, были значительно улучшены.

  (Добавлено Бенджамином Петерсоном.)

## Более детальная блокировка импорта

Предыдущие версии CPython всегда полагались на глобальную блокировку импорта. Это приводило к неожиданным неудобствам, таким как взаимоблокировки, когда импорт модуля вызывал побочное выполнение кода в другом потоке. Иногда использовались неуклюжие обходные пути, например, функция [`PyImport_ImportModuleNoBlock()`](https://python-all.ru/3.9/c-api/import.html#c.PyImport_ImportModuleNoBlock) из C API.

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

(Добавлено Антуаном Питу в [bpo-9260](https://python-all.ru/3.9/whatsnew/3.3.html).)

## Встроенные функции и типы

- [`open()`](https://python-all.ru/3.9/library/functions.html#open) получил новый параметр *opener*: базовый файловый дескриптор для файлового объекта затем получается вызовом *opener* с (*file*, *flags*). Его можно использовать для задания нестандартных флагов, например [`os.O_CLOEXEC`](https://python-all.ru/3.9/library/os.html#os.O_CLOEXEC). Добавлен режим `'x'`: открытие для исключительного создания, с ошибкой, если файл уже существует.
- [`print()`](https://python-all.ru/3.9/library/functions.html#print): добавлен именованный аргумент *flush*. Если именованный аргумент *flush* истинен, поток принудительно сбрасывается.
- [`hash()`](https://python-all.ru/3.9/library/functions.html#hash): рандомизация хэша включена по умолчанию, см. [`object.__hash__()`](https://python-all.ru/3.9/reference/datamodel.html#object.__hash__) и [`PYTHONHASHSEED`](https://python-all.ru/3.9/using/cmdline.html#envvar-PYTHONHASHSEED).
- Тип [`str`](https://python-all.ru/3.9/library/stdtypes.html#str) получил новый метод [`casefold()`](https://python-all.ru/3.9/library/stdtypes.html#str.casefold): возвращает копию строки со свёрткой регистра; такие строки могут использоваться для регистронезависимого сравнения. Например, `'ß'.casefold()` возвращает `'ss'`.
- Документация по последовательностям была существенно переписана, чтобы лучше объяснять различие между двоичными и текстовыми последовательностями и предоставить отдельные разделы документации для каждого встроенного типа последовательностей ([bpo-4966](https://python-all.ru/3.9/whatsnew/3.3.html)).

## Новые модули

### faulthandler

Этот новый модуль отладки [`faulthandler`](https://python-all.ru/3.9/library/faulthandler.html#module-faulthandler) содержит функции для явного дампа трасс стека Python при сбое (аварийном завершении, например, ошибке сегментации), по истечении тайм-аута или по сигналу пользователя. Вызов [`faulthandler.enable()`](https://python-all.ru/3.9/library/faulthandler.html#faulthandler.enable) устанавливает обработчики сбоев для сигналов `SIGSEGV`, `SIGFPE`, `SIGABRT`, `SIGBUS` и `SIGILL`. Также можно включить их при запуске, установив переменную окружения [`PYTHONFAULTHANDLER`](https://python-all.ru/3.9/using/cmdline.html#envvar-PYTHONFAULTHANDLER) или используя параметр командной строки [`-X`](https://python-all.ru/3.9/using/cmdline.html#id5) `faulthandler`.

Пример ошибки сегментации в Linux:

```console
$ python -q -X faulthandler
>>> import ctypes
>>> ctypes.string_at(0)
Fatal Python error: Segmentation fault

Current thread 0x00007fb899f39700:
  File "/home/python/cpython/Lib/ctypes/__init__.py", line 486 in string_at
  File "<stdin>", line 1 in <module>
Segmentation fault
```

### ipaddress

Новый модуль [`ipaddress`](https://python-all.ru/3.9/library/ipaddress.html#module-ipaddress) предоставляет инструменты для создания и управления объектами, представляющими адреса IPv4 и IPv6, сети и интерфейсы (т.е. IP-адрес, связанный с определённой подсетью).

(Добавлено Google и Питером Муди в [**PEP 3144**](https://python-all.ru/3.9/whatsnew/3.3.html).)

### lzma

Недавно добавленный модуль [`lzma`](https://python-all.ru/3.9/library/lzma.html#module-lzma) обеспечивает сжатие и распаковку данных с использованием алгоритма LZMA, включая поддержку `.xz` и `.lzma` форматов файлов.

(Добавлено Надимом Вавдой и Пером Эйвиндом Карлсеном в [bpo-6715](https://python-all.ru/3.9/whatsnew/3.3.html).)

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

### abc

Улучшена поддержка абстрактных базовых классов, содержащих дескрипторы, составленные из абстрактных методов. Рекомендуемый способ объявления абстрактных дескрипторов – теперь предоставлять `__isabstractmethod__` как динамически обновляемое свойство. Встроенные дескрипторы были соответствующим образом обновлены.

> - [`abc.abstractproperty`](https://python-all.ru/3.9/library/abc.html#abc.abstractproperty) объявлен устаревшим, вместо него используйте [`property`](https://python-all.ru/3.9/library/functions.html#property) с [`abc.abstractmethod()`](https://python-all.ru/3.9/library/abc.html#abc.abstractmethod).
> - [`abc.abstractclassmethod`](https://python-all.ru/3.9/library/abc.html#abc.abstractclassmethod) объявлен устаревшим, вместо него используйте [`classmethod`](https://python-all.ru/3.9/library/functions.html#classmethod) с [`abc.abstractmethod()`](https://python-all.ru/3.9/library/abc.html#abc.abstractmethod).
> - [`abc.abstractstaticmethod`](https://python-all.ru/3.9/library/abc.html#abc.abstractstaticmethod) объявлен устаревшим, вместо него используйте [`staticmethod`](https://python-all.ru/3.9/library/functions.html#staticmethod) с [`abc.abstractmethod()`](https://python-all.ru/3.9/library/abc.html#abc.abstractmethod).

(Автор – Даррен Дейл в [bpo-11610](https://python-all.ru/3.9/whatsnew/3.3.html).)

[`abc.ABCMeta.register()`](https://python-all.ru/3.9/library/abc.html#abc.ABCMeta.register) теперь возвращает зарегистрированный подкласс, что позволяет использовать его в качестве декоратора класса ([bpo-10868](https://python-all.ru/3.9/whatsnew/3.3.html)).

### array

Модуль [`array`](https://python-all.ru/3.9/library/array.html#module-array) поддерживает тип `long long` с помощью кодов типа `q` и `Q`.

(Авторы – Орен Тирош и Хирокадзу Ямамото в [bpo-1172711](https://python-all.ru/3.9/whatsnew/3.3.html).)

### base64

Функции декодирования [`base64`](https://python-all.ru/3.9/library/base64.html#module-base64) современного интерфейса теперь принимают строки Unicode, состоящие только из ASCII. Например, `base64.b64decode('YWJj')` возвращает `b'abc'`. (Автор – Каталин Якоб в [bpo-13641](https://python-all.ru/3.9/whatsnew/3.3.html).)

### binascii

Помимо обычных бинарных объектов, функции `a2b_` теперь также принимают на вход строки, состоящие только из ASCII. (Автор – Антуан Питу в [bpo-13637](https://python-all.ru/3.9/whatsnew/3.3.html).)

### bz2

Модуль [`bz2`](https://python-all.ru/3.9/library/bz2.html#module-bz2) был переписан с нуля. В процессе было добавлено несколько новых возможностей:

- Новая функция [`bz2.open()`](https://python-all.ru/3.9/library/bz2.html#bz2.open): открытие файла, сжатого bzip2, в бинарном или текстовом режиме.
- [`bz2.BZ2File`](https://python-all.ru/3.9/library/bz2.html#bz2.BZ2File) теперь может читать и писать в произвольные объекты, похожие на файлы, с помощью аргумента *fileobj* своего конструктора.

  (Автор – Надим Вовда в [bpo-5863](https://python-all.ru/3.9/whatsnew/3.3.html).)
- [`bz2.BZ2File`](https://python-all.ru/3.9/library/bz2.html#bz2.BZ2File) и [`bz2.decompress()`](https://python-all.ru/3.9/library/bz2.html#bz2.decompress) теперь могут декомпрессировать многопоточные входные данные (например, созданные утилитой **pbzip2**). [`bz2.BZ2File`](https://python-all.ru/3.9/library/bz2.html#bz2.BZ2File) также можно использовать для создания файлов такого типа – в режиме `'a'` (добавление).

  (Автор – Нир Айдес в [bpo-1625](https://python-all.ru/3.9/whatsnew/3.3.html).)
- [`bz2.BZ2File`](https://python-all.ru/3.9/library/bz2.html#bz2.BZ2File) теперь реализует весь API [`io.BufferedIOBase`](https://python-all.ru/3.9/library/io.html#io.BufferedIOBase), за исключением методов `detach()` и `truncate()`.

### codecs

Кодек [`mbcs`](https://python-all.ru/3.9/library/codecs.html#module-encodings.mbcs) был переписан для корректной обработки обработчиков ошибок `replace` и `ignore` во всех версиях Windows. Кодек [`mbcs`](https://python-all.ru/3.9/library/codecs.html#module-encodings.mbcs) теперь поддерживает все обработчики ошибок, а не только `replace` при кодировании и `ignore` при декодировании.

Добавлен новый кодек только для Windows: `cp65001` ([bpo-13216](https://python-all.ru/3.9/whatsnew/3.3.html)). Это кодовая страница Windows 65001 (Windows UTF-8, `CP_UTF8`). Например, он используется `sys.stdout`, если кодовая страница вывода консоли установлена на cp65001 (например, с помощью команды `chcp 65001`).

Многобайтовые декодеры CJK теперь быстрее ресинхронизируются. Они игнорируют только первый байт недопустимой последовательности байтов. Например, `b'\xff\n'.decode('gb2312', 'replace')` теперь возвращает `\n` после символа замены.

([bpo-12016](https://python-all.ru/3.9/whatsnew/3.3.html))

Инкрементальные кодировщики кодеков CJK больше не сбрасываются при каждом вызове их метода encode(). Например:

```python
>>> import codecs
>>> encoder = codecs.getincrementalencoder('hz')('strict')
>>> b''.join(encoder.encode(x) for x in '\u52ff\u65bd\u65bc\u4eba\u3002 Bye.')
b'~{NpJ)l6HK!#~} Bye.'
```

Этот пример возвращает `b'~{Np~}~{J)~}~{l6~}~{HK~}~{!#~} Bye.'` в старых версиях Python.

([bpo-12100](https://python-all.ru/3.9/whatsnew/3.3.html))

Кодек `unicode_internal` устарел.

### collections

Добавлен новый класс [`ChainMap`](https://python-all.ru/3.9/library/collections.html#collections.ChainMap) для работы с несколькими отображениями как с единым целым. (Написан Раймондом Хеттингером для [bpo-11089](https://python-all.ru/3.9/whatsnew/3.3.html), опубликован в [bpo-11297](https://python-all.ru/3.9/whatsnew/3.3.html).)

Абстрактные базовые классы были перенесены в новый модуль [`collections.abc`](https://python-all.ru/3.9/library/collections.abc.html#module-collections.abc), чтобы лучше разграничить абстрактные и конкретные классы коллекций. Псевдонимы для ABC по-прежнему присутствуют в модуле [`collections`](https://python-all.ru/3.9/library/collections.html#module-collections) для сохранения существующих импортов. ([bpo-11085](https://python-all.ru/3.9/whatsnew/3.3.html))

Класс [`Counter`](https://python-all.ru/3.9/library/collections.html#collections.Counter) теперь поддерживает унарные операторы `+` и `-`, а также операторы на месте `+=`, `-=`, `|=` и `&=`. (Автор – Раймонд Хеттингер в [bpo-13121](https://python-all.ru/3.9/whatsnew/3.3.html).)

### contextlib

[`ExitStack`](https://python-all.ru/3.9/library/contextlib.html#contextlib.ExitStack) теперь предоставляет прочную основу для программного управления менеджерами контекста и аналогичной функциональности очистки. В отличие от предыдущего API `contextlib.nested` (который был объявлен устаревшим и удалён), новый API спроектирован так, чтобы корректно работать независимо от того, получают ли менеджеры контекста свои ресурсы в методе `__init__` (например, файловые объекты) или в методе `__enter__` (например, объекты синхронизации из модуля [`threading`](https://python-all.ru/3.9/library/threading.html#module-threading)).

([bpo-13585](https://python-all.ru/3.9/whatsnew/3.3.html))

### crypt

Добавление соли и модульного формата crypt (метода хеширования), а также функции [`mksalt()`](https://python-all.ru/3.9/library/crypt.html#crypt.mksalt) в модуль [`crypt`](https://python-all.ru/3.9/library/crypt.html#module-crypt).

([bpo-10924](https://python-all.ru/3.9/whatsnew/3.3.html))

### curses

> - Если модуль [`curses`](https://python-all.ru/3.9/library/curses.html#module-curses) слинкован с библиотекой ncursesw, следует использовать функции Unicode при передаче строк или символов Unicode (например, `waddwstr()`), а в остальных случаях – функции для bytes (например, `waddstr()`).
> - Для кодирования строк Unicode используется кодировка локали вместо `utf-8`.
> - У `curses.window` появился новый атрибут [`curses.window.encoding`](https://python-all.ru/3.9/library/curses.html#curses.window.encoding).
> - У класса `curses.window` появился новый метод [`get_wch()`](https://python-all.ru/3.9/library/curses.html#curses.window.get_wch) для получения широкого символа.
> - У модуля [`curses`](https://python-all.ru/3.9/library/curses.html#module-curses) появилась новая функция [`unget_wch()`](https://python-all.ru/3.9/library/curses.html#curses.unget_wch), которая помещает широкий символ, чтобы следующий вызов [`get_wch()`](https://python-all.ru/3.9/library/curses.html#curses.window.get_wch) вернул его.

(Автор: Iñigo Serna; [bpo-6755](https://python-all.ru/3.9/whatsnew/3.3.html).)

### datetime

> - Сравнения на равенство между наивными и осведомлёнными экземплярами [`datetime`](https://python-all.ru/3.9/library/datetime.html#datetime.datetime) теперь возвращают [`False`](https://python-all.ru/3.9/library/constants.html#False) вместо выброса исключения [`TypeError`](https://python-all.ru/3.9/library/exceptions.html#TypeError) ([bpo-15006](https://python-all.ru/3.9/whatsnew/3.3.html)).
> - Новый метод [`datetime.datetime.timestamp()`](https://python-all.ru/3.9/library/datetime.html#datetime.datetime.timestamp): возвращает POSIX-временную метку для экземпляра [`datetime`](https://python-all.ru/3.9/library/datetime.html#datetime.datetime).
> - Метод [`datetime.datetime.strftime()`](https://python-all.ru/3.9/library/datetime.html#datetime.datetime.strftime) поддерживает форматирование годов до 1000 года.
> - Метод [`datetime.datetime.astimezone()`](https://python-all.ru/3.9/library/datetime.html#datetime.datetime.astimezone) теперь можно вызывать без аргументов для преобразования экземпляра datetime в системный часовой пояс.

### decimal

**[bpo-7652](https://python-all.ru/3.9/whatsnew/3.3.html) – интеграция быстрой встроенной десятичной арифметики.**

C-модуль и libmpdec написаны Stefan Krah.

Новая версия модуля decimal на C включает в себя высокоскоростную библиотеку libmpdec которая обеспечивает арифметику с плавающей точкой произвольной точности и правильным округлением. libmpdec соответствует спецификации IBM General Decimal Arithmetic Specification.

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

Приведённая ниже таблица предназначена для иллюстрации. Бенчмарки доступны по адресу [http://www.bytereef.org/mpdecimal/quickstart.html](https://python-all.ru/3.9/whatsnew/3.3.html).

> |  | decimal.py | \_decimal | ускорение |
> | --- | --- | --- | --- |
> | pi | 42.02s | 0.345s | 120x |
> | telco | 172.19s | 5.68s | 30x |
> | psycopg | 3.57s | 0.29s | 12x |

#### Возможности

- Сигнал [`FloatOperation`](https://python-all.ru/3.9/library/decimal.html#decimal.FloatOperation) опционально включает более строгую семантику для смешивания чисел с плавающей запятой и десятичных чисел.
- Если Python скомпилирован без поддержки потоков, C-версия автоматически отключает дорогостоящий механизм контекста, локального для потока. В этом случае переменная [`HAVE_THREADS`](https://python-all.ru/3.9/library/decimal.html#decimal.HAVE_THREADS) устанавливается в `False`.

#### Изменения API

- C-модуль имеет следующие ограничения контекста в зависимости от архитектуры машины:

  > |  | 32-битный | 64-битный |
  > | --- | --- | --- |
  > | `MAX_PREC` | `425000000` | `999999999999999999` |
  > | `MAX_EMAX` | `425000000` | `999999999999999999` |
  > | `MIN_EMIN` | `-425000000` | `-999999999999999999` |
- В шаблонах контекста ([`DefaultContext`](https://python-all.ru/3.9/library/decimal.html#decimal.DefaultContext), [`BasicContext`](https://python-all.ru/3.9/library/decimal.html#decimal.BasicContext) и [`ExtendedContext`](https://python-all.ru/3.9/library/decimal.html#decimal.ExtendedContext)) величина `Emax` и `Emin` изменилась на `999999`.
- Конструктор [`Decimal`](https://python-all.ru/3.9/library/decimal.html#decimal.Decimal) в decimal.py не соблюдает ограничения контекста и преобразует значения с произвольными показателями степени или точностью точно. Поскольку C-версия имеет внутренние ограничения, используется следующая схема: если возможно, значения преобразуются точно, в противном случае возбуждается [`InvalidOperation`](https://python-all.ru/3.9/library/decimal.html#decimal.InvalidOperation) и результат равен NaN. В последнем случае всегда можно использовать [`create_decimal()`](https://python-all.ru/3.9/library/decimal.html#decimal.Context.create_decimal), чтобы получить округлённое или неточное значение.
- Функция возведения в степень в decimal.py всегда правильно округляется. В версии на C она определяется через правильно округлённые функции [`exp()`](https://python-all.ru/3.9/library/decimal.html#decimal.Decimal.exp) и [`ln()`](https://python-all.ru/3.9/library/decimal.html#decimal.Decimal.ln), но конечный результат округлён «почти всегда правильно».
- В C-версии словарь контекста, содержащий сигналы, является [`MutableMapping`](https://python-all.ru/3.9/library/collections.abc.html#collections.abc.MutableMapping). По соображениям быстродействия `flags` и `traps` всегда ссылаются на тот же [`MutableMapping`](https://python-all.ru/3.9/library/collections.abc.html#collections.abc.MutableMapping), с которым был инициализирован контекст. Если присваивается новый словарь сигналов, `flags` и `traps` обновляются новыми значениями, но не ссылаются на словарь из правой части присваивания.
- Упаковка [`Context`](https://python-all.ru/3.9/library/decimal.html#decimal.Context) даёт другой вывод, чтобы иметь общий формат обмена для Python и C-версий.
- Порядок аргументов в конструкторе [`Context`](https://python-all.ru/3.9/library/decimal.html#decimal.Context) был изменён, чтобы соответствовать порядку, отображаемому [`repr()`](https://python-all.ru/3.9/library/functions.html#repr).
- Параметр `watchexp` в методе [`quantize()`](https://python-all.ru/3.9/library/decimal.html#decimal.Decimal.quantize) устарел.

### email

#### Инфраструктура политик

Пакет email теперь имеет каркас [`policy`](https://python-all.ru/3.9/library/email.policy.html#module-email.policy). [`Policy`](https://python-all.ru/3.9/library/email.policy.html#email.policy.Policy) – это объект с несколькими методами и свойствами, управляющими поведением пакета email. Основной политикой для Python 3.3 является политика [`Compat32`](https://python-all.ru/3.9/library/email.policy.html#email.policy.Compat32), обеспечивающая обратную совместимость с пакетом email в Python 3.2. `policy` можно указать при разборе сообщения электронной почты с помощью [`parser`](https://python-all.ru/3.9/library/email.parser.html#module-email.parser), при создании объекта [`Message`](https://python-all.ru/3.9/library/email.compat32-message.html#email.message.Message) или при сериализации сообщения с помощью [`generator`](https://python-all.ru/3.9/library/email.generator.html#module-email.generator). Если не переопределена, политика, переданная в `parser`, наследуется всеми объектами `Message` и подобъектами, созданными `parser`. По умолчанию `generator` использует политику объекта `Message`, который он сериализует. Политикой по умолчанию является [`compat32`](https://python-all.ru/3.9/library/email.policy.html#email.policy.compat32).

Минимальный набор параметров управления, реализованный всеми объектами `policy`:

> | max\_line\_length | Максимальная длина (без учёта символа(ов) linesep), которую могут иметь отдельные строки при сериализации `Message`. По умолчанию 78. |
> | --- | --- |
> | linesep | Символ, используемый для разделения отдельных строк при сериализации `Message`. По умолчанию `\n`. |
> | cte\_type | `7bit` или `8bit`. `8bit` применяется только к `Bytes` `generator` и означает, что не-ASCII может использоваться там, где это разрешено протоколом (или где оно присутствует в исходных данных). |
> | raise\_on\_defect | Заставляет `parser` возбуждать ошибку при обнаружении дефектов вместо добавления их в список `defects` объекта `Message`. |

Новый экземпляр политики с новыми настройками создаётся с помощью метода [`clone()`](https://python-all.ru/3.9/library/email.policy.html#email.policy.Policy.clone) объектов политики. `clone` принимает любые из перечисленных выше параметров управления в качестве именованных аргументов. Любой параметр, не указанный в вызове, сохраняет значение по умолчанию. Так можно создать политику, использующую символы `\r\n` linesep, следующим образом:

```python
mypolicy = compat32.clone(linesep='\r\n')
```

Политики можно использовать, чтобы упростить создание сообщений в формате, необходимом вашей программе. Вместо того чтобы помнить об указании `linesep='\r\n'` во всех местах, где вызывается `generator`, можно указать его один раз при настройке политики, используемой объектом `parser` или `Message` (в зависимости от того, что использует ваша программа для создания объектов `Message`). С другой стороны, если нужно создавать сообщения в нескольких форматах, можно по-прежнему указывать параметры в соответствующем вызове `generator`. Или можно создать собственные экземпляры политик для разных случаев и передавать их при создании объекта `generator`.

#### Временная политика с новым API заголовков

Хотя сама по себе структура политик (policy) представляет ценность, основная причина её введения – дать возможность создавать новые политики, реализующие новые возможности для пакета email, таким образом, чтобы сохранялась обратная совместимость для тех, кто не использует новые политики. Поскольку новые политики вводят новый API, мы выпускаем их в Python 3.3 как [предварительную политику](https://python-all.ru/3.9/glossary.html#term-provisional-package). Изменения, нарушающие обратную совместимость (вплоть до удаления кода), могут быть внесены, если основные разработчики сочтут это необходимым.

Новые политики являются экземплярами [`EmailPolicy`](https://python-all.ru/3.9/library/email.policy.html#email.policy.EmailPolicy) и добавляют следующие дополнительные средства управления:

> | refold\_source | Определяет, будут ли заголовки, разобранные с помощью [`parser`](https://python-all.ru/3.9/library/email.parser.html#module-email.parser), переформатированы (refolded) с помощью [`generator`](https://python-all.ru/3.9/library/email.generator.html#module-email.generator). Может принимать значения `none`, `long` или `all`. По умолчанию `long`, что означает, что исходные заголовки, длина строки которых превышает `max_line_length`, переформатируются. `none` означает, что строки не переформатируются, а `all` – что переформатируются все строки. |
> | --- | --- |
> | header\_factory | Вызываемый объект, который принимает `name` и `value` и создаёт пользовательский объект заголовка. |

`header_factory` – ключ к новым возможностям, предоставляемым новыми политиками. При использовании одной из новых политик любой заголовок, полученный из объекта `Message`, является объектом, созданным `header_factory`, и всякий раз, когда вы задаёте заголовок в `Message`, он становится объектом, созданным `header_factory`. Все такие объекты заголовков имеют атрибут `name`, равный имени заголовка. Заголовки Address и Date имеют дополнительные атрибуты, дающие доступ к разобранным данным заголовка. Это означает, что теперь можно делать следующее:

```python
>>> m = Message(policy=SMTP)
>>> m['To'] = 'Éric <foo@example.com>'
>>> m['to']
'Éric <foo@example.com>'
>>> m['to'].addresses
(Address(display_name='Éric', username='foo', domain='example.com'),)
>>> m['to'].addresses[0].username
'foo'
>>> m['to'].addresses[0].display_name
'Éric'
>>> m['Date'] = email.utils.localtime()
>>> m['Date'].datetime
datetime.datetime(2012, 5, 25, 21, 39, 24, 465484, tzinfo=datetime.timezone(datetime.timedelta(-1, 72000), 'EDT'))
>>> m['Date']
'Fri, 25 May 2012 21:44:27 -0400'
>>> print(m)
To: =?utf-8?q?=C3=89ric?= <foo@example.com>
Date: Fri, 25 May 2012 21:44:27 -0400
```

Обратите внимание: отображаемое имя в Юникоде автоматически кодируется как `utf-8` при сериализации сообщения, но при прямом доступе к заголовку вы получаете версию в Юникоде. Это устраняет необходимость иметь дело с функциями [`email.header`](https://python-all.ru/3.9/library/email.header.html#module-email.header) [`decode_header()`](https://python-all.ru/3.9/library/email.header.html#email.header.decode_header) или [`make_header()`](https://python-all.ru/3.9/library/email.header.html#email.header.make_header).

Также можно создавать адреса из частей:

```python
>>> m['cc'] = [Group('pals', [Address('Bob', 'bob', 'example.com'),
...                           Address('Sally', 'sally', 'example.com')]),
...            Address('Bonzo', addr_spec='bonz@laugh.com')]
>>> print(m)
To: =?utf-8?q?=C3=89ric?= <foo@example.com>
Date: Fri, 25 May 2012 21:44:27 -0400
cc: pals: Bob <bob@example.com>, Sally <sally@example.com>;, Bonzo <bonz@laugh.com>
```

Декодирование в Юникод выполняется автоматически:

```python
>>> m2 = message_from_string(str(m))
>>> m2['to']
'Éric <foo@example.com>'
```

При разборе сообщения можно использовать атрибуты `addresses` и `groups` объектов заголовков для доступа к группам и отдельным адресам:

```python
>>> m2['cc'].addresses
(Address(display_name='Bob', username='bob', domain='example.com'), Address(display_name='Sally', username='sally', domain='example.com'), Address(display_name='Bonzo', username='bonz', domain='laugh.com'))
>>> m2['cc'].groups
(Group(display_name='pals', addresses=(Address(display_name='Bob', username='bob', domain='example.com'), Address(display_name='Sally', username='sally', domain='example.com')), Group(display_name=None, addresses=(Address(display_name='Bonzo', username='bonz', domain='laugh.com'),))
```

В итоге, если вы используете одну из новых политик, работа с заголовками происходит так, как и должна: ваше приложение работает со строками Юникода, а пакет email прозрачно кодирует и декодирует Юникод в стандартные кодировки передачи содержимого (Content Transfer Encodings) RFC и обратно.

#### Другие изменения API

Новый [`BytesHeaderParser`](https://python-all.ru/3.9/library/email.parser.html#email.parser.BytesHeaderParser), добавленный в модуль [`parser`](https://python-all.ru/3.9/library/email.parser.html#module-email.parser) в дополнение к [`HeaderParser`](https://python-all.ru/3.9/library/email.parser.html#email.parser.HeaderParser) и для завершения Bytes API.

Новые вспомогательные функции:

> - [`format_datetime()`](https://python-all.ru/3.9/library/email.utils.html#email.utils.format_datetime): принимая [`datetime`](https://python-all.ru/3.9/library/datetime.html#datetime.datetime), возвращает строку, отформатированную для использования в заголовке email.
> - [`parsedate_to_datetime()`](https://python-all.ru/3.9/library/email.utils.html#email.utils.parsedate_to_datetime): принимая строку даты из заголовка email, преобразует её в осознанный (aware) объект [`datetime`](https://python-all.ru/3.9/library/datetime.html#datetime.datetime) или наивный (naive) объект [`datetime`](https://python-all.ru/3.9/library/datetime.html#datetime.datetime), если смещение равно `-0000`.
> - [`localtime()`](https://python-all.ru/3.9/library/email.utils.html#email.utils.localtime): без аргументов возвращает текущее местное время как осознанный (aware) объект [`datetime`](https://python-all.ru/3.9/library/datetime.html#datetime.datetime) с использованием местного [`timezone`](https://python-all.ru/3.9/library/datetime.html#datetime.timezone). Принимая осознанный объект [`datetime`](https://python-all.ru/3.9/library/datetime.html#datetime.datetime), преобразует его в осознанный объект [`datetime`](https://python-all.ru/3.9/library/datetime.html#datetime.datetime) с использованием местного [`timezone`](https://python-all.ru/3.9/library/datetime.html#datetime.timezone).

### ftplib

- [`ftplib.FTP`](https://python-all.ru/3.9/library/ftplib.html#ftplib.FTP) теперь принимает именованный аргумент `source_address` для указания `(host, port)`, используемого в качестве исходного адреса в вызове bind при создании исходящего сокета. (Автор: Giampaolo Rodolà в [bpo-8594](https://python-all.ru/3.9/whatsnew/3.3.html).)
- Класс [`FTP_TLS`](https://python-all.ru/3.9/library/ftplib.html#ftplib.FTP_TLS) теперь предоставляет новую функцию [`ccc()`](https://python-all.ru/3.9/library/ftplib.html#ftplib.FTP_TLS.ccc) для возврата управляющего канала в открытый текст (plaintext). Это может быть полезно для использования межсетевых экранов, которые умеют обрабатывать NAT с небезопасным FTP без открытия фиксированных портов. (Автор: Giampaolo Rodolà в [bpo-12139](https://python-all.ru/3.9/whatsnew/3.3.html).)
- Добавлен метод [`ftplib.FTP.mlsd()`](https://python-all.ru/3.9/library/ftplib.html#ftplib.FTP.mlsd), который предоставляет разбираемый формат списка каталогов и заменяет устаревшие [`ftplib.FTP.nlst()`](https://python-all.ru/3.9/library/ftplib.html#ftplib.FTP.nlst) и [`ftplib.FTP.dir()`](https://python-all.ru/3.9/library/ftplib.html#ftplib.FTP.dir). (Автор: Giampaolo Rodolà в [bpo-11072](https://python-all.ru/3.9/whatsnew/3.3.html).)

### functools

Декоратор [`functools.lru_cache()`](https://python-all.ru/3.9/library/functools.html#functools.lru_cache) теперь принимает именованный аргумент `typed` (по умолчанию `False`), чтобы гарантировать кэширование значений разных типов, которые сравниваются как равные, в отдельных слотах кэша. (Автор: Raymond Hettinger в [bpo-13227](https://python-all.ru/3.9/whatsnew/3.3.html).)

### gc

Теперь можно регистрировать колбэки, вызываемые сборщиком мусора до и после сборки, с помощью нового списка [`callbacks`](https://python-all.ru/3.9/library/gc.html#gc.callbacks).

### hmac

Добавлена новая функция [`compare_digest()`](https://python-all.ru/3.9/library/hmac.html#hmac.compare_digest) для предотвращения атак по побочным каналам на дайджесты через анализ времени выполнения. (Авторы: Nick Coghlan и Christian Heimes в [bpo-15061](https://python-all.ru/3.9/whatsnew/3.3.html).)

### http

[`http.server.BaseHTTPRequestHandler`](https://python-all.ru/3.9/library/http.server.html#http.server.BaseHTTPRequestHandler) теперь буферизует заголовки и записывает их все сразу при вызове [`end_headers()`](https://python-all.ru/3.9/library/http.server.html#http.server.BaseHTTPRequestHandler.end_headers). Новый метод [`flush_headers()`](https://python-all.ru/3.9/library/http.server.html#http.server.BaseHTTPRequestHandler.flush_headers) можно использовать для прямого управления моментом отправки накопленных заголовков. (Автор: Andrew Schaaf в [bpo-3709](https://python-all.ru/3.9/whatsnew/3.3.html).)

[`http.server`](https://python-all.ru/3.9/library/http.server.html#module-http.server) теперь создаёт корректный вывод `HTML 4.01 strict`. (Автор: Ezio Melotti в [bpo-13295](https://python-all.ru/3.9/whatsnew/3.3.html).)

[`http.client.HTTPResponse`](https://python-all.ru/3.9/library/http.client.html#http.client.HTTPResponse) теперь имеет метод [`readinto()`](https://python-all.ru/3.9/library/http.client.html#http.client.HTTPResponse.readinto), что позволяет использовать его как класс [`io.RawIOBase`](https://python-all.ru/3.9/library/io.html#io.RawIOBase). (Автор: John Kuhn в [bpo-13464](https://python-all.ru/3.9/whatsnew/3.3.html).)

### html

[`html.parser.HTMLParser`](https://python-all.ru/3.9/library/html.parser.html#html.parser.HTMLParser) теперь может разбирать некорректную разметку без возникновения ошибок, поэтому аргумент *strict* конструктора и исключение `HTMLParseError` теперь считаются устаревшими. Возможность разбирать некорректную разметку стала результатом ряда исправлений ошибок, которые также доступны в последних выпусках с исправлениями ошибок Python 2.7/3.2. (Автор: Ezio Melotti в [bpo-15114](https://python-all.ru/3.9/whatsnew/3.3.html), и [bpo-14538](https://python-all.ru/3.9/whatsnew/3.3.html), [bpo-13993](https://python-all.ru/3.9/whatsnew/3.3.html), [bpo-13960](https://python-all.ru/3.9/whatsnew/3.3.html), [bpo-13358](https://python-all.ru/3.9/whatsnew/3.3.html), [bpo-1745761](https://python-all.ru/3.9/whatsnew/3.3.html), [bpo-755670](https://python-all.ru/3.9/whatsnew/3.3.html), [bpo-13357](https://python-all.ru/3.9/whatsnew/3.3.html), [bpo-12629](https://python-all.ru/3.9/whatsnew/3.3.html), [bpo-1200313](https://python-all.ru/3.9/whatsnew/3.3.html), [bpo-670664](https://python-all.ru/3.9/whatsnew/3.3.html), [bpo-13273](https://python-all.ru/3.9/whatsnew/3.3.html), [bpo-12888](https://python-all.ru/3.9/whatsnew/3.3.html), [bpo-7311](https://python-all.ru/3.9/whatsnew/3.3.html).)

Новый словарь [`html5`](https://python-all.ru/3.9/library/html.entities.html#html.entities.html5), который сопоставляет именованные ссылки на символы HTML5 с эквивалентными символами Юникода (например, `html5['gt;'] == '>'`), был добавлен в модуль [`html.entities`](https://python-all.ru/3.9/library/html.entities.html#module-html.entities). Этот словарь теперь также используется [`HTMLParser`](https://python-all.ru/3.9/library/html.parser.html#html.parser.HTMLParser). (Автор: Ezio Melotti в [bpo-11113](https://python-all.ru/3.9/whatsnew/3.3.html) и [bpo-15156](https://python-all.ru/3.9/whatsnew/3.3.html).)

### imaplib

Конструктор [`IMAP4_SSL`](https://python-all.ru/3.9/library/imaplib.html#imaplib.IMAP4_SSL) теперь принимает параметр SSLContext для управления параметрами защищённого канала.

(Автор: Sijin Joseph в [bpo-8808](https://python-all.ru/3.9/whatsnew/3.3.html).)

### inspect

Добавлена новая функция [`getclosurevars()`](https://python-all.ru/3.9/library/inspect.html#inspect.getclosurevars). Эта функция сообщает о текущей привязке всех имён, на которые есть ссылки из тела функции, и о том, где эти имена были разрешены, что упрощает проверку корректности внутреннего состояния при тестировании кода, полагающегося на замыкания с состоянием.

(Авторы: Meador Inge и Nick Coghlan в [bpo-13062](https://python-all.ru/3.9/whatsnew/3.3.html).)

Добавлена новая функция [`getgeneratorlocals()`](https://python-all.ru/3.9/library/inspect.html#inspect.getgeneratorlocals). Эта функция сообщает о текущей привязке локальных переменных в стековом фрейме генератора, что упрощает проверку корректности внутреннего состояния при тестировании генераторов.

(Автор: Meador Inge в [bpo-15153](https://python-all.ru/3.9/whatsnew/3.3.html).)

### io

Функция [`open()`](https://python-all.ru/3.9/library/io.html#io.open) получила новый режим `'x'`, который можно использовать для исключительного создания нового файла, и вызывает исключение [`FileExistsError`](https://python-all.ru/3.9/library/exceptions.html#FileExistsError), если файл уже существует. Он основан на режиме 'x' из C11 для fopen().

(Автор: David Townshend в [bpo-12760](https://python-all.ru/3.9/whatsnew/3.3.html).)

Конструктор класса [`TextIOWrapper`](https://python-all.ru/3.9/library/io.html#io.TextIOWrapper) получил новый необязательный аргумент *write\_through*. Если *write\_through* равен `True`, вызовы `write()` гарантированно не буферизуются: любые данные, записанные в объект [`TextIOWrapper`](https://python-all.ru/3.9/library/io.html#io.TextIOWrapper), немедленно передаются его нижележащему двоичному буферу.

### itertools

[`accumulate()`](https://python-all.ru/3.9/library/itertools.html#itertools.accumulate) теперь принимает необязательный аргумент `func` для указания бинарной функции, предоставленной пользователем.

### logging

Функция [`basicConfig()`](https://python-all.ru/3.9/library/logging.html#logging.basicConfig) теперь поддерживает необязательный аргумент `handlers`, принимающий итерируемый объект обработчиков, которые будут добавлены к корневому логгеру.

Добавлен атрибут уровня класса `append_nul` в [`SysLogHandler`](https://python-all.ru/3.9/library/logging.handlers.html#logging.handlers.SysLogHandler), позволяющий управлять добавлением байта `NUL` (`\000`) к записям syslog, поскольку для некоторых демонов он обязателен, а для других он передаётся в журнал.

### math

Модуль [`math`](https://python-all.ru/3.9/library/math.html#module-math) получил новую функцию [`log2()`](https://python-all.ru/3.9/library/math.html#math.log2), которая возвращает двоичный логарифм *x*.

(Написан Mark Dickinson в [bpo-11888](https://python-all.ru/3.9/whatsnew/3.3.html).)

### mmap

Метод [`read()`](https://python-all.ru/3.9/library/mmap.html#mmap.mmap.read) теперь более совместим с другими файлоподобными объектами: если аргумент опущен или указан как `None`, он возвращает байты от текущей позиции файла до конца отображения. (Автор: Petri Lehtinen в [bpo-12021](https://python-all.ru/3.9/whatsnew/3.3.html).)

### multiprocessing

Новая функция [`multiprocessing.connection.wait()`](https://python-all.ru/3.9/library/multiprocessing.html#multiprocessing.connection.wait) позволяет опрашивать несколько объектов (таких как соединения, сокеты и каналы) с таймаутом. (Автор: Richard Oudkerk в [bpo-12328](https://python-all.ru/3.9/whatsnew/3.3.html).)

`multiprocessing.Connection` объекты теперь можно передавать через соединения multiprocessing. (Вклад от Richard Oudkerk в [bpo-4892](https://python-all.ru/3.9/whatsnew/3.3.html).)

[`multiprocessing.Process`](https://python-all.ru/3.9/library/multiprocessing.html#multiprocessing.Process) теперь принимает именованный аргумент `daemon`, чтобы переопределить поведение по умолчанию, заключающееся в наследовании флага `daemon` от родительского процесса ([bpo-6064](https://python-all.ru/3.9/whatsnew/3.3.html)).

Новый атрибут [`multiprocessing.Process.sentinel`](https://python-all.ru/3.9/library/multiprocessing.html#multiprocessing.Process.sentinel) позволяет программе ожидать несколько объектов [`Process`](https://python-all.ru/3.9/library/multiprocessing.html#multiprocessing.Process) одновременно, используя соответствующие примитивы ОС (например, [`select`](https://python-all.ru/3.9/library/select.html#module-select) в системах POSIX).

Новые методы [`multiprocessing.pool.Pool.starmap()`](https://python-all.ru/3.9/library/multiprocessing.html#multiprocessing.pool.Pool.starmap) и [`starmap_async()`](https://python-all.ru/3.9/library/multiprocessing.html#multiprocessing.pool.Pool.starmap_async) предоставляют [`itertools.starmap()`](https://python-all.ru/3.9/library/itertools.html#itertools.starmap)-эквиваленты существующих функций [`multiprocessing.pool.Pool.map()`](https://python-all.ru/3.9/library/multiprocessing.html#multiprocessing.pool.Pool.map) и [`map_async()`](https://python-all.ru/3.9/library/multiprocessing.html#multiprocessing.pool.Pool.map_async). (Автор: Hynek Schlawack в [bpo-12708](https://python-all.ru/3.9/whatsnew/3.3.html).)

### nntplib

Класс [`nntplib.NNTP`](https://python-all.ru/3.9/library/nntplib.html#nntplib.NNTP) теперь поддерживает протокол управления контекстом для безусловного поглощения исключений [`socket.error`](https://python-all.ru/3.9/library/socket.html#socket.error) и закрытия NNTP-соединения по завершении:

```python
>>> from nntplib import NNTP
>>> with NNTP('news.gmane.org') as n:
...     n.group('gmane.comp.python.committers')
...
('211 1755 1 1755 gmane.comp.python.committers', 1755, 1, 1755, 'gmane.comp.python.committers')
>>>
```

(Предложено Giampaolo Rodolà в [bpo-9795](https://python-all.ru/3.9/whatsnew/3.3.html).)

### os

- В модуле [`os`](https://python-all.ru/3.9/library/os.html#module-os) появилась новая функция [`pipe2()`](https://python-all.ru/3.9/library/os.html#os.pipe2), позволяющая атомарно создать канал с флагами [`O_CLOEXEC`](https://python-all.ru/3.9/library/os.html#os.O_CLOEXEC) или [`O_NONBLOCK`](https://python-all.ru/3.9/library/os.html#os.O_NONBLOCK). Это особенно полезно для предотвращения состояний гонки в многопоточных программах.
- В модуле [`os`](https://python-all.ru/3.9/library/os.html#module-os) появилась новая функция [`sendfile()`](https://python-all.ru/3.9/library/os.html#os.sendfile), предоставляющая эффективный способ «нулевого копирования» для передачи данных от одного файлового (или сокетного) дескриптора к другому. Термин «нулевое копирование» означает, что всё копирование данных между двумя дескрипторами полностью выполняется ядром, без копирования данных в буферы пользовательского пространства. [`sendfile()`](https://python-all.ru/3.9/library/os.html#os.sendfile) можно использовать для эффективного копирования данных из файла на диске в сетевой сокет, например, для загрузки файла.

  (Патч предоставлен Ross Lagerwall и Giampaolo Rodolà в [bpo-10882](https://python-all.ru/3.9/whatsnew/3.3.html).)
- Чтобы избежать состояний гонки, таких как атаки через символические ссылки и проблемы с временными файлами и каталогами, надёжнее (и быстрее) работать с файловыми дескрипторами, а не с именами файлов. Python 3.3 расширяет существующие функции и добавляет новые для работы с файловыми дескрипторами ([bpo-4761](https://python-all.ru/3.9/whatsnew/3.3.html), [bpo-10755](https://python-all.ru/3.9/whatsnew/3.3.html) и [bpo-14626](https://python-all.ru/3.9/whatsnew/3.3.html)).

  - В модуле [`os`](https://python-all.ru/3.9/library/os.html#module-os) появилась новая функция [`fwalk()`](https://python-all.ru/3.9/library/os.html#os.fwalk), похожая на [`walk()`](https://python-all.ru/3.9/library/os.html#os.walk), но дополнительно возвращающая файловые дескрипторы посещённых каталогов. Это особенно полезно для предотвращения состояний гонки с символическими ссылками.
  - Следующие функции получили новые необязательные параметры *dir\_fd* ([пути относительно дескрипторов каталогов](https://python-all.ru/3.9/library/os.html#dir-fd)) и/или *follow\_symlinks* ([не следовать символическим ссылкам](https://python-all.ru/3.9/library/os.html#follow-symlinks)): [`access()`](https://python-all.ru/3.9/library/os.html#os.access), [`chflags()`](https://python-all.ru/3.9/library/os.html#os.chflags), [`chmod()`](https://python-all.ru/3.9/library/os.html#os.chmod), [`chown()`](https://python-all.ru/3.9/library/os.html#os.chown), [`link()`](https://python-all.ru/3.9/library/os.html#os.link), [`lstat()`](https://python-all.ru/3.9/library/os.html#os.lstat), [`mkdir()`](https://python-all.ru/3.9/library/os.html#os.mkdir), [`mkfifo()`](https://python-all.ru/3.9/library/os.html#os.mkfifo), [`mknod()`](https://python-all.ru/3.9/library/os.html#os.mknod), [`open()`](https://python-all.ru/3.9/library/os.html#os.open), [`readlink()`](https://python-all.ru/3.9/library/os.html#os.readlink), [`remove()`](https://python-all.ru/3.9/library/os.html#os.remove), [`rename()`](https://python-all.ru/3.9/library/os.html#os.rename), [`replace()`](https://python-all.ru/3.9/library/os.html#os.replace), [`rmdir()`](https://python-all.ru/3.9/library/os.html#os.rmdir), [`stat()`](https://python-all.ru/3.9/library/os.html#os.stat), [`symlink()`](https://python-all.ru/3.9/library/os.html#os.symlink), [`unlink()`](https://python-all.ru/3.9/library/os.html#os.unlink), [`utime()`](https://python-all.ru/3.9/library/os.html#os.utime). Поддержка платформой этих параметров проверяется через множества [`os.supports_dir_fd`](https://python-all.ru/3.9/library/os.html#os.supports_dir_fd) и `os.supports_follows_symlinks`.
  - Следующие функции теперь поддерживают файловый дескриптор в качестве аргумента path: [`chdir()`](https://python-all.ru/3.9/library/os.html#os.chdir), [`chmod()`](https://python-all.ru/3.9/library/os.html#os.chmod), [`chown()`](https://python-all.ru/3.9/library/os.html#os.chown), [`execve()`](https://python-all.ru/3.9/library/os.html#os.execve), [`listdir()`](https://python-all.ru/3.9/library/os.html#os.listdir), [`pathconf()`](https://python-all.ru/3.9/library/os.html#os.pathconf), [`exists()`](https://python-all.ru/3.9/library/os.path.html#os.path.exists), [`stat()`](https://python-all.ru/3.9/library/os.html#os.stat), [`statvfs()`](https://python-all.ru/3.9/library/os.html#os.statvfs), [`utime()`](https://python-all.ru/3.9/library/os.html#os.utime). Поддержка этой возможности на конкретной платформе проверяется через множество [`os.supports_fd`](https://python-all.ru/3.9/library/os.html#os.supports_fd).
- [`access()`](https://python-all.ru/3.9/library/os.html#os.access) принимает именованный аргумент `effective_ids` для включения использования эффективного uid/gid вместо реального uid/gid при проверке доступа. Поддержка этой возможности на конкретной платформе проверяется через множество [`supports_effective_ids`](https://python-all.ru/3.9/library/os.html#os.supports_effective_ids).
- В модуле [`os`](https://python-all.ru/3.9/library/os.html#module-os) появились две новые функции: [`getpriority()`](https://python-all.ru/3.9/library/os.html#os.getpriority) и [`setpriority()`](https://python-all.ru/3.9/library/os.html#os.setpriority). Они используются для получения или установки приоритета (niceness) процесса аналогично [`os.nice()`](https://python-all.ru/3.9/library/os.html#os.nice), но для всех процессов, а не только текущего.

  (Патч предоставлен Giampaolo Rodolà в [bpo-10784](https://python-all.ru/3.9/whatsnew/3.3.html).)
- Новая функция [`os.replace()`](https://python-all.ru/3.9/library/os.html#os.replace) позволяет кроссплатформенное переименование файла с перезаписью целевого файла. При использовании [`os.rename()`](https://python-all.ru/3.9/library/os.html#os.rename) существующий целевой файл перезаписывается в POSIX, но вызывает ошибку в Windows. (Предложено Antoine Pitrou в [bpo-8828](https://python-all.ru/3.9/whatsnew/3.3.html).)
- Семейство функций stat ([`stat()`](https://python-all.ru/3.9/library/os.html#os.stat), [`fstat()`](https://python-all.ru/3.9/library/os.html#os.fstat) и [`lstat()`](https://python-all.ru/3.9/library/os.html#os.lstat)) теперь поддерживает чтение временных меток файла с наносекундной точностью. Симметрично, [`utime()`](https://python-all.ru/3.9/library/os.html#os.utime) теперь может записывать временные метки с наносекундной точностью. (Предложено Larry Hastings в [bpo-14127](https://python-all.ru/3.9/whatsnew/3.3.html).)
- Новая функция [`os.get_terminal_size()`](https://python-all.ru/3.9/library/os.html#os.get_terminal_size) запрашивает размер терминала, подключённого к файловому дескриптору. См. также [`shutil.get_terminal_size()`](https://python-all.ru/3.9/library/shutil.html#shutil.get_terminal_size). (Предложено Zbigniew Jędrzejewski-Szmek в [bpo-13609](https://python-all.ru/3.9/whatsnew/3.3.html).)

- Новые функции для поддержки расширенных атрибутов Linux ([bpo-12720](https://python-all.ru/3.9/whatsnew/3.3.html)): [`getxattr()`](https://python-all.ru/3.9/library/os.html#os.getxattr), [`listxattr()`](https://python-all.ru/3.9/library/os.html#os.listxattr), [`removexattr()`](https://python-all.ru/3.9/library/os.html#os.removexattr), [`setxattr()`](https://python-all.ru/3.9/library/os.html#os.setxattr).
- Новый интерфейс к планировщику. Эти функции управляют тем, как операционная система выделяет процессу процессорное время. Новые функции: [`sched_get_priority_max()`](https://python-all.ru/3.9/library/os.html#os.sched_get_priority_max), [`sched_get_priority_min()`](https://python-all.ru/3.9/library/os.html#os.sched_get_priority_min), [`sched_getaffinity()`](https://python-all.ru/3.9/library/os.html#os.sched_getaffinity), [`sched_getparam()`](https://python-all.ru/3.9/library/os.html#os.sched_getparam), [`sched_getscheduler()`](https://python-all.ru/3.9/library/os.html#os.sched_getscheduler), [`sched_rr_get_interval()`](https://python-all.ru/3.9/library/os.html#os.sched_rr_get_interval), [`sched_setaffinity()`](https://python-all.ru/3.9/library/os.html#os.sched_setaffinity), [`sched_setparam()`](https://python-all.ru/3.9/library/os.html#os.sched_setparam), [`sched_setscheduler()`](https://python-all.ru/3.9/library/os.html#os.sched_setscheduler), [`sched_yield()`](https://python-all.ru/3.9/library/os.html#os.sched_yield).
- Новые функции для управления файловой системой:

  - [`posix_fadvise()`](https://python-all.ru/3.9/library/os.html#os.posix_fadvise): Объявляет о намерении обращаться к данным по определённому шаблону, позволяя ядру выполнять оптимизации.
  - [`posix_fallocate()`](https://python-all.ru/3.9/library/os.html#os.posix_fallocate): Гарантирует, что для файла выделено достаточно дискового пространства.
  - [`sync()`](https://python-all.ru/3.9/library/os.html#os.sync): Принудительная запись всего на диск.
- Дополнительные новые функции POSIX:

  - [`lockf()`](https://python-all.ru/3.9/library/os.html#os.lockf): Установить, проверить или снять блокировку POSIX на открытом файловом дескрипторе.
  - [`pread()`](https://python-all.ru/3.9/library/os.html#os.pread): Чтение из файлового дескриптора по смещению; смещение в файле не изменяется.
  - [`pwrite()`](https://python-all.ru/3.9/library/os.html#os.pwrite): Запись в файловый дескриптор по смещению; смещение в файле не изменяется.
  - [`readv()`](https://python-all.ru/3.9/library/os.html#os.readv): Чтение из файлового дескриптора в несколько буферов для записи.
  - [`truncate()`](https://python-all.ru/3.9/library/os.html#os.truncate): Усекает файл, соответствующий *path*, так чтобы его размер был не больше *length* байт.
  - [`waitid()`](https://python-all.ru/3.9/library/os.html#os.waitid): Ожидание завершения одного или нескольких дочерних процессов.
  - [`writev()`](https://python-all.ru/3.9/library/os.html#os.writev): Записывает содержимое *buffers* в файловый дескриптор, где *buffers* – произвольная последовательность буферов.
  - [`getgrouplist()`](https://python-all.ru/3.9/library/os.html#os.getgrouplist) ([bpo-9344](https://python-all.ru/3.9/whatsnew/3.3.html)): Возвращает список идентификаторов групп, которым принадлежит указанный пользователь.
- [`times()`](https://python-all.ru/3.9/library/os.html#os.times) и [`uname()`](https://python-all.ru/3.9/library/os.html#os.uname): Тип возвращаемого значения изменён с кортежа на объект, похожий на кортеж, с именованными атрибутами.
- Некоторые платформы теперь поддерживают дополнительные константы для [`lseek()`](https://python-all.ru/3.9/library/os.html#os.lseek) функции, такие как `os.SEEK_HOLE` и `os.SEEK_DATA`.
- Новые константы [`RTLD_LAZY`](https://python-all.ru/3.9/library/os.html#os.RTLD_LAZY), [`RTLD_NOW`](https://python-all.ru/3.9/library/os.html#os.RTLD_NOW), [`RTLD_GLOBAL`](https://python-all.ru/3.9/library/os.html#os.RTLD_GLOBAL), [`RTLD_LOCAL`](https://python-all.ru/3.9/library/os.html#os.RTLD_LOCAL), [`RTLD_NODELETE`](https://python-all.ru/3.9/library/os.html#os.RTLD_NODELETE), [`RTLD_NOLOAD`](https://python-all.ru/3.9/library/os.html#os.RTLD_NOLOAD), [`RTLD_DEEPBIND`](https://python-all.ru/3.9/library/os.html#os.RTLD_DEEPBIND) доступны на платформах, которые их поддерживают. Они предназначены для использования с функцией [`sys.setdlopenflags()`](https://python-all.ru/3.9/library/sys.html#sys.setdlopenflags) и заменяют аналогичные константы, определённые в [`ctypes`](https://python-all.ru/3.9/library/ctypes.html#module-ctypes) и `DLFCN`. (Добавлено Виктором Стиннером в [bpo-13226](https://python-all.ru/3.9/whatsnew/3.3.html).)
- [`os.symlink()`](https://python-all.ru/3.9/library/os.html#os.symlink) теперь принимает (и игнорирует) аргумент `target_is_directory` на платформах, отличных от Windows, для упрощения кроссплатформенной поддержки.

### pdb

Автодополнение по табуляции теперь доступно не только для имён команд, но и для их аргументов. Например, для команды `break` дополняются имена функций и файлов.

(Добавлено Георгом Брандлом в [bpo-14210](https://python-all.ru/3.9/whatsnew/3.3.html))

### pickle

Объекты [`pickle.Pickler`](https://python-all.ru/3.9/library/pickle.html#pickle.Pickler) теперь имеют необязательный атрибут [`dispatch_table`](https://python-all.ru/3.9/library/pickle.html#pickle.Pickler.dispatch_table), позволяющий задавать функции сокращения (reduction) для каждого pickler.

(Добавлено Ричардом Аудкерком в [bpo-14166](https://python-all.ru/3.9/whatsnew/3.3.html).)

### pydoc

Графический интерфейс Tk и функция `serve()` удалены из модуля [`pydoc`](https://python-all.ru/3.9/library/pydoc.html#module-pydoc): `pydoc -g` и `serve()` объявлены устаревшими в Python 3.2.

### re

[`str`](https://python-all.ru/3.9/library/stdtypes.html#str) регулярные выражения теперь поддерживают `\u` и `\U` управляющие последовательности.

(Добавлено Сергием Сторчакой в [bpo-3665](https://python-all.ru/3.9/whatsnew/3.3.html).)

### sched

- [`run()`](https://python-all.ru/3.9/library/sched.html#sched.scheduler.run) теперь принимает параметр *blocking*, который при установке в значение False заставляет метод выполнить запланированные события с истекающим сроком (если такие есть) и затем немедленно вернуться. Это полезно, если требуется использовать [`scheduler`](https://python-all.ru/3.9/library/sched.html#sched.scheduler) в неблокирующих приложениях. (Добавлено Джампаоло Родола в [bpo-13449](https://python-all.ru/3.9/whatsnew/3.3.html).)
- Класс [`scheduler`](https://python-all.ru/3.9/library/sched.html#sched.scheduler) теперь можно безопасно использовать в многопоточных средах. (Добавлено Джозайей Карлсоном и Джампаоло Родола в [bpo-8684](https://python-all.ru/3.9/whatsnew/3.3.html).)
- Параметры *timefunc* и *delayfunct* конструктора класса [`scheduler`](https://python-all.ru/3.9/library/sched.html#sched.scheduler) теперь являются необязательными и по умолчанию равны [`time.time()`](https://python-all.ru/3.9/library/time.html#time.time) и [`time.sleep()`](https://python-all.ru/3.9/library/time.html#time.sleep) соответственно. (Добавлено Крисом Кларком в [bpo-13245](https://python-all.ru/3.9/whatsnew/3.3.html).)
- Параметр *argument* у [`enter()`](https://python-all.ru/3.9/library/sched.html#sched.scheduler.enter) и [`enterabs()`](https://python-all.ru/3.9/library/sched.html#sched.scheduler.enterabs) теперь необязателен. (Добавлено Крисом Кларком в [bpo-13245](https://python-all.ru/3.9/whatsnew/3.3.html).)
- [`enter()`](https://python-all.ru/3.9/library/sched.html#sched.scheduler.enter) и [`enterabs()`](https://python-all.ru/3.9/library/sched.html#sched.scheduler.enterabs) теперь принимают параметр *kwargs*. (Добавлено Крисом Кларком в [bpo-13245](https://python-all.ru/3.9/whatsnew/3.3.html).)

### select

На платформах Solaris и производных появился новый класс [`select.devpoll`](https://python-all.ru/3.9/library/select.html#select.devpoll) для высокопроизводительных асинхронных сокетов через `/dev/poll`. (Добавлено Хесусом Сеа Авионом в [bpo-6397](https://python-all.ru/3.9/whatsnew/3.3.html).)

### shlex

Ранее недокументированная вспомогательная функция `quote` из модуля [`pipes`](https://python-all.ru/3.9/library/pipes.html#module-pipes) была перенесена в модуль [`shlex`](https://python-all.ru/3.9/library/shlex.html#module-shlex) и задокументирована. [`quote()`](https://python-all.ru/3.9/library/shlex.html#shlex.quote) корректно экранирует все символы в строке, которые в противном случае могли бы получить специальное значение в оболочке.

### shutil

- Новые функции:

  - [`disk_usage()`](https://python-all.ru/3.9/library/shutil.html#shutil.disk_usage): предоставляет статистику общего, используемого и свободного дискового пространства. (Добавлено Джампаоло Родола в [bpo-12442](https://python-all.ru/3.9/whatsnew/3.3.html).)
  - [`chown()`](https://python-all.ru/3.9/library/shutil.html#shutil.chown): позволяет изменить пользователя и/или группу для указанного пути, указывая имена пользователя/группы, а не только их числовые идентификаторы. (Добавлено Сандро Този в [bpo-12191](https://python-all.ru/3.9/whatsnew/3.3.html).)
  - [`shutil.get_terminal_size()`](https://python-all.ru/3.9/library/shutil.html#shutil.get_terminal_size): возвращает размер окна терминала, к которому привязан интерпретатор. (Добавлено Збигневом Енджеевским-Шмеком в [bpo-13609](https://python-all.ru/3.9/whatsnew/3.3.html).)
- [`copy2()`](https://python-all.ru/3.9/library/shutil.html#shutil.copy2) и [`copystat()`](https://python-all.ru/3.9/library/shutil.html#shutil.copystat) теперь сохраняют временные метки файлов с точностью до наносекунд на платформах, которые это поддерживают. Они также сохраняют «расширенные атрибуты» файлов в Linux. (Добавлено Ларри Хастингсом в [bpo-14127](https://python-all.ru/3.9/whatsnew/3.3.html) и [bpo-15238](https://python-all.ru/3.9/whatsnew/3.3.html).)
- Несколько функций теперь принимают необязательный аргумент `symlinks`: если этот параметр равен True, символические ссылки не разыменовываются, и операция вместо этого воздействует на саму символическую ссылку (или создаёт её, если применимо). (Добавлено Хайнеком Шлаваком в [bpo-12715](https://python-all.ru/3.9/whatsnew/3.3.html).)
- При копировании файлов в другую файловую систему [`move()`](https://python-all.ru/3.9/library/shutil.html#shutil.move) теперь обрабатывает символические ссылки так же, как команда posix `mv`: создаёт ссылку заново, а не копирует содержимое целевого файла. (Добавлено Джонатаном Нихофом в [bpo-9993](https://python-all.ru/3.9/whatsnew/3.3.html).) [`move()`](https://python-all.ru/3.9/library/shutil.html#shutil.move) теперь также возвращает аргумент `dst` в качестве своего результата.
- [`rmtree()`](https://python-all.ru/3.9/library/shutil.html#shutil.rmtree) теперь устойчив к атакам через симлинки на платформах, поддерживающих новый параметр `dir_fd` в [`os.open()`](https://python-all.ru/3.9/library/os.html#os.open) и [`os.unlink()`](https://python-all.ru/3.9/library/os.html#os.unlink). (Авторы: Martin von Löwis и Hynek Schlawack в [bpo-4489](https://python-all.ru/3.9/whatsnew/3.3.html).)

### signal

- В модуле [`signal`](https://python-all.ru/3.9/library/signal.html#module-signal) появились новые функции:

  - [`pthread_sigmask()`](https://python-all.ru/3.9/library/signal.html#signal.pthread_sigmask): получение и/или изменение маски сигналов вызывающего потока (Автор: Jean-Paul Calderone в [bpo-8407](https://python-all.ru/3.9/whatsnew/3.3.html));
  - [`pthread_kill()`](https://python-all.ru/3.9/library/signal.html#signal.pthread_kill): отправка сигнала потоку;
  - [`sigpending()`](https://python-all.ru/3.9/library/signal.html#signal.sigpending): проверка ожидающих функций;
  - [`sigwait()`](https://python-all.ru/3.9/library/signal.html#signal.sigwait): ожидание сигнала;
  - [`sigwaitinfo()`](https://python-all.ru/3.9/library/signal.html#signal.sigwaitinfo): ожидание сигнала с возвратом подробной информации о нём;
  - [`sigtimedwait()`](https://python-all.ru/3.9/library/signal.html#signal.sigtimedwait): как [`sigwaitinfo()`](https://python-all.ru/3.9/library/signal.html#signal.sigwaitinfo), но с таймаутом.
- Обработчик сигнала записывает номер сигнала в виде одного байта вместо нулевого байта в файловый дескриптор пробуждения. Таким образом, можно ожидать более одного сигнала и узнавать, какие сигналы были вызваны.
- [`signal.signal()`](https://python-all.ru/3.9/library/signal.html#signal.signal) и [`signal.siginterrupt()`](https://python-all.ru/3.9/library/signal.html#signal.siginterrupt) вызывают OSError, вместо RuntimeError: OSError имеет атрибут errno.

### smtpd

Модуль [`smtpd`](https://python-all.ru/3.9/library/smtpd.html#module-smtpd) теперь поддерживает [**RFC 5321**](https://python-all.ru/3.9/whatsnew/3.3.html) (расширенный SMTP) и [**RFC 1870**](https://python-all.ru/3.9/whatsnew/3.3.html) (расширение размера). В соответствии со стандартом, эти расширения включаются тогда и только тогда, когда клиент начинает сеанс с команды `EHLO`.

(Начальная поддержка `ELHO` реализована Alberto Trevino. Расширение размера – Juhana Jauhiainen. Значительный дополнительный вклад в патч внесли Michele Orrù и Dan Boswell. [bpo-8739](https://python-all.ru/3.9/whatsnew/3.3.html))

### smtplib

Классы [`SMTP`](https://python-all.ru/3.9/library/smtplib.html#smtplib.SMTP), [`SMTP_SSL`](https://python-all.ru/3.9/library/smtplib.html#smtplib.SMTP_SSL) и [`LMTP`](https://python-all.ru/3.9/library/smtplib.html#smtplib.LMTP) теперь принимают именованный аргумент `source_address` для указания `(host, port)`, используемого в качестве исходного адреса в вызове bind при создании исходящего сокета. (Автор: Paulo Scardine в [bpo-11281](https://python-all.ru/3.9/whatsnew/3.3.html).)

[`SMTP`](https://python-all.ru/3.9/library/smtplib.html#smtplib.SMTP) теперь поддерживает протокол менеджера контекста, что позволяет использовать экземпляр `SMTP` в операторе `with`. (Автор: Giampaolo Rodolà в [bpo-11289](https://python-all.ru/3.9/whatsnew/3.3.html).)

Конструктор [`SMTP_SSL`](https://python-all.ru/3.9/library/smtplib.html#smtplib.SMTP_SSL) и метод [`starttls()`](https://python-all.ru/3.9/library/smtplib.html#smtplib.SMTP.starttls) теперь принимают параметр SSLContext для управления параметрами защищённого канала. (Автор: Kasun Herath в [bpo-8809](https://python-all.ru/3.9/whatsnew/3.3.html).)

### socket

- Класс [`socket`](https://python-all.ru/3.9/library/socket.html#socket.socket) теперь предоставляет дополнительные методы для обработки вспомогательных данных, если это поддерживается платформой:

  - [`sendmsg()`](https://python-all.ru/3.9/library/socket.html#socket.socket.sendmsg)
  - [`recvmsg()`](https://python-all.ru/3.9/library/socket.html#socket.socket.recvmsg)
  - [`recvmsg_into()`](https://python-all.ru/3.9/library/socket.html#socket.socket.recvmsg_into)

  (Автор: David Watson в [bpo-6560](https://python-all.ru/3.9/whatsnew/3.3.html), на основе более раннего патча от Heiko Wundram)
- Класс [`socket`](https://python-all.ru/3.9/library/socket.html#socket.socket) теперь поддерживает семейство протоколов PF\_CAN ([https://en.wikipedia.org/wiki/Socketcan](https://python-all.ru/3.9/whatsnew/3.3.html)) на Linux ([https://lwn.net/Articles/253425](https://python-all.ru/3.9/whatsnew/3.3.html)).

  (Автор: Matthias Fuchs, обновлено Tiago Gonçalves в [bpo-10141](https://python-all.ru/3.9/whatsnew/3.3.html).)
- Класс [`socket`](https://python-all.ru/3.9/library/socket.html#socket.socket) теперь поддерживает семейство протоколов PF\_RDS ([https://en.wikipedia.org/wiki/Reliable\_Datagram\_Sockets](https://python-all.ru/3.9/whatsnew/3.3.html) и [https://oss.oracle.com/projects/rds/](https://python-all.ru/3.9/whatsnew/3.3.html)).
- Класс [`socket`](https://python-all.ru/3.9/library/socket.html#socket.socket) теперь поддерживает семейство протоколов `PF_SYSTEM` на OS X. (Автор: Michael Goderbauer в [bpo-13777](https://python-all.ru/3.9/whatsnew/3.3.html).)
- Новая функция [`sethostname()`](https://python-all.ru/3.9/library/socket.html#socket.sethostname) позволяет задавать имя хоста в системах Unix, если у вызывающего процесса достаточно привилегий. (Автор: Ross Lagerwall, [bpo-10866](https://python-all.ru/3.9/whatsnew/3.3.html).)

### socketserver

[`BaseServer`](https://python-all.ru/3.9/library/socketserver.html#socketserver.BaseServer) теперь имеет переопределяемый метод [`service_actions()`](https://python-all.ru/3.9/library/socketserver.html#socketserver.BaseServer.service_actions), который вызывается методом [`serve_forever()`](https://python-all.ru/3.9/library/socketserver.html#socketserver.BaseServer.serve_forever) в сервисном цикле. [`ForkingMixIn`](https://python-all.ru/3.9/library/socketserver.html#socketserver.ForkingMixIn) теперь использует это для очистки зомби-процессов дочерних процессов. (Автор: Justin Warkentin в [bpo-11109](https://python-all.ru/3.9/whatsnew/3.3.html).)

### sqlite3

Новый метод [`sqlite3.Connection`](https://python-all.ru/3.9/library/sqlite3.html#sqlite3.Connection) [`set_trace_callback()`](https://python-all.ru/3.9/library/sqlite3.html#sqlite3.Connection.set_trace_callback) можно использовать для захвата трассировки всех команд SQL, обрабатываемых sqlite. (Автор: Torsten Landschoff в [bpo-11688](https://python-all.ru/3.9/whatsnew/3.3.html).)

### ssl

- Модуль [`ssl`](https://python-all.ru/3.9/library/ssl.html#module-ssl) содержит две новые функции генерации случайных чисел:

  - [`RAND_bytes()`](https://python-all.ru/3.9/library/ssl.html#ssl.RAND_bytes): генерирует криптостойкие псевдослучайные байты.
  - [`RAND_pseudo_bytes()`](https://python-all.ru/3.9/library/ssl.html#ssl.RAND_pseudo_bytes): генерирует псевдослучайные байты.

  (Предложено Victor Stinner в [bpo-12049](https://python-all.ru/3.9/whatsnew/3.3.html).)
- Модуль [`ssl`](https://python-all.ru/3.9/library/ssl.html#module-ssl) теперь предоставляет более детализированную иерархию исключений, чтобы упростить анализ различных типов ошибок. (Предложено Antoine Pitrou в [bpo-11183](https://python-all.ru/3.9/whatsnew/3.3.html).)
- [`load_cert_chain()`](https://python-all.ru/3.9/library/ssl.html#ssl.SSLContext.load_cert_chain) теперь принимает аргумент *password* для использования, если закрытый ключ зашифрован. (Предложено Adam Simpkins в [bpo-12803](https://python-all.ru/3.9/whatsnew/3.3.html).)
- Обмен ключами Диффи-Хеллмана, как обычный, так и на основе эллиптических кривых, теперь поддерживается через методы [`load_dh_params()`](https://python-all.ru/3.9/library/ssl.html#ssl.SSLContext.load_dh_params) и [`set_ecdh_curve()`](https://python-all.ru/3.9/library/ssl.html#ssl.SSLContext.set_ecdh_curve). (Предложено Antoine Pitrou в [bpo-13626](https://python-all.ru/3.9/whatsnew/3.3.html) и [bpo-13627](https://python-all.ru/3.9/whatsnew/3.3.html).)
- SSL-сокеты получили новый метод [`get_channel_binding()`](https://python-all.ru/3.9/library/ssl.html#ssl.SSLSocket.get_channel_binding), позволяющий реализовать определённые механизмы аутентификации, такие как SCRAM-SHA-1-PLUS. (Предложено Jacek Konieczny в [bpo-12551](https://python-all.ru/3.9/whatsnew/3.3.html).)
- Можно запросить алгоритм сжатия SSL, используемый SSL-сокетом, благодаря его новому методу [`compression()`](https://python-all.ru/3.9/library/ssl.html#ssl.SSLSocket.compression). Новый атрибут [`OP_NO_COMPRESSION`](https://python-all.ru/3.9/library/ssl.html#ssl.OP_NO_COMPRESSION) можно использовать для отключения сжатия. (Предложено Antoine Pitrou в [bpo-13634](https://python-all.ru/3.9/whatsnew/3.3.html).)
- Добавлена поддержка расширения согласования следующего протокола (Next Protocol Negotiation) с использованием метода [`ssl.SSLContext.set_npn_protocols()`](https://python-all.ru/3.9/library/ssl.html#ssl.SSLContext.set_npn_protocols). (Предложено Colin Marc в [bpo-14204](https://python-all.ru/3.9/whatsnew/3.3.html).)
- Теперь ошибки SSL можно легче анализировать благодаря атрибутам [`library`](https://python-all.ru/3.9/library/ssl.html#ssl.SSLError.library) и [`reason`](https://python-all.ru/3.9/library/ssl.html#ssl.SSLError.reason). (Предложено Antoine Pitrou в [bpo-14837](https://python-all.ru/3.9/whatsnew/3.3.html).)
- Функция [`get_server_certificate()`](https://python-all.ru/3.9/library/ssl.html#ssl.get_server_certificate) теперь поддерживает IPv6. (Предложено Charles-François Natali в [bpo-11811](https://python-all.ru/3.9/whatsnew/3.3.html).)
- Новый атрибут [`OP_CIPHER_SERVER_PREFERENCE`](https://python-all.ru/3.9/library/ssl.html#ssl.OP_CIPHER_SERVER_PREFERENCE) позволяет настроить серверные сокеты SSLv3 на использование предпочтений сервера в порядке шифров, а не клиента ([bpo-13635](https://python-all.ru/3.9/whatsnew/3.3.html)).

### stat

Не документированная функция tarfile.filemode перемещена в [`stat.filemode()`](https://python-all.ru/3.9/library/stat.html#stat.filemode). Её можно использовать для преобразования режима файла в строку вида ‘-rwxrwxrwx’.

(Предложено Giampaolo Rodolà в [bpo-14807](https://python-all.ru/3.9/whatsnew/3.3.html).)

### struct

Модуль [`struct`](https://python-all.ru/3.9/library/struct.html#module-struct) теперь поддерживает `ssize_t` и `size_t` через новые коды `n` и `N` соответственно. (Предложено Antoine Pitrou в [bpo-3163](https://python-all.ru/3.9/whatsnew/3.3.html).)

### подпроцесс

Строки команд теперь могут быть объектами bytes на платформах POSIX. (Предложено Victor Stinner в [bpo-8513](https://python-all.ru/3.9/whatsnew/3.3.html).)

Новая константа [`DEVNULL`](https://python-all.ru/3.9/library/subprocess.html#subprocess.DEVNULL) позволяет подавлять вывод платформонезависимым способом. (Предложено Ross Lagerwall в [bpo-5870](https://python-all.ru/3.9/whatsnew/3.3.html).)

### sys

Модуль [`sys`](https://python-all.ru/3.9/library/sys.html#module-sys) имеет новый [`thread_info`](https://python-all.ru/3.9/library/sys.html#sys.thread_info) [именованный кортеж](https://python-all.ru/3.9/glossary.html#term-named-tuple), содержащий информацию о реализации потоков ([bpo-11223](https://python-all.ru/3.9/whatsnew/3.3.html)).

### tarfile

[`tarfile`](https://python-all.ru/3.9/library/tarfile.html#module-tarfile) теперь поддерживает кодировку `lzma` через модуль [`lzma`](https://python-all.ru/3.9/library/lzma.html#module-lzma). (Предложено Lars Gustäbel в [bpo-5689](https://python-all.ru/3.9/whatsnew/3.3.html).)

### tempfile

Метод `truncate()` объекта [`tempfile.SpooledTemporaryFile`](https://python-all.ru/3.9/library/tempfile.html#tempfile.SpooledTemporaryFile) теперь принимает параметр `size`. (Добавлено Райаном Келли в [bpo-9957](https://python-all.ru/3.9/whatsnew/3.3.html).)

### textwrap

Модуль [`textwrap`](https://python-all.ru/3.9/library/textwrap.html#module-textwrap) имеет новый [`indent()`](https://python-all.ru/3.9/library/textwrap.html#textwrap.indent), который упрощает добавление общего префикса к выбранным строкам в блоке текста ([bpo-13857](https://python-all.ru/3.9/whatsnew/3.3.html)).

### threading

[`threading.Condition`](https://python-all.ru/3.9/library/threading.html#threading.Condition), [`threading.Semaphore`](https://python-all.ru/3.9/library/threading.html#threading.Semaphore), [`threading.BoundedSemaphore`](https://python-all.ru/3.9/library/threading.html#threading.BoundedSemaphore), [`threading.Event`](https://python-all.ru/3.9/library/threading.html#threading.Event) и [`threading.Timer`](https://python-all.ru/3.9/library/threading.html#threading.Timer), которые раньше были фабричными функциями, возвращающими экземпляр класса, теперь являются классами и могут быть унаследованы. (Предложено Éric Araujo в [bpo-10968](https://python-all.ru/3.9/whatsnew/3.3.html).)

Конструктор [`threading.Thread`](https://python-all.ru/3.9/library/threading.html#threading.Thread) теперь принимает именованный аргумент `daemon` для переопределения поведения по умолчанию, при котором значение флага `daemon` наследуется от родительского потока ([bpo-6064](https://python-all.ru/3.9/whatsnew/3.3.html)).

Ранее закрытая функция `_thread.get_ident` теперь доступна как публичная функция [`threading.get_ident()`](https://python-all.ru/3.9/library/threading.html#threading.get_ident). Это устраняет несколько случаев прямого доступа к модулю `_thread` в стандартной библиотеке. Сторонний код, который использовал `_thread.get_ident`, следует аналогичным образом изменить для использования нового публичного интерфейса.

### time

[**PEP 418**](https://python-all.ru/3.9/whatsnew/3.3.html) добавил новые функции в модуль [`time`](https://python-all.ru/3.9/library/time.html#module-time):

- [`get_clock_info()`](https://python-all.ru/3.9/library/time.html#time.get_clock_info): получение информации о часах.
- [`monotonic()`](https://python-all.ru/3.9/library/time.html#time.monotonic): монотонные часы (не могут идти назад), не подвержены влиянию обновлений системных часов.
- [`perf_counter()`](https://python-all.ru/3.9/library/time.html#time.perf_counter): счетчик производительности с максимально доступным разрешением для измерения коротких промежутков времени.
- [`process_time()`](https://python-all.ru/3.9/library/time.html#time.process_time): сумма системного и пользовательского времени ЦП текущего процесса.

Другие новые функции:

- [`clock_getres()`](https://python-all.ru/3.9/library/time.html#time.clock_getres), [`clock_gettime()`](https://python-all.ru/3.9/library/time.html#time.clock_gettime) и [`clock_settime()`](https://python-all.ru/3.9/library/time.html#time.clock_settime) функции с константами `CLOCK_xxx`. (Добавлено Виктором Стиннером в [bpo-10278](https://python-all.ru/3.9/whatsnew/3.3.html).)

Для улучшения кроссплатформенной согласованности [`sleep()`](https://python-all.ru/3.9/library/time.html#time.sleep) теперь вызывает [`ValueError`](https://python-all.ru/3.9/library/exceptions.html#ValueError) при передаче отрицательного значения sleep. Ранее это было ошибкой в POSIX, но приводило к бесконечному сну в Windows.

### types

Добавлен новый класс [`types.MappingProxyType`](https://python-all.ru/3.9/library/types.html#types.MappingProxyType): прокси только для чтения отображения. ([bpo-14386](https://python-all.ru/3.9/whatsnew/3.3.html))

Новые функции [`types.new_class()`](https://python-all.ru/3.9/library/types.html#types.new_class) и [`types.prepare_class()`](https://python-all.ru/3.9/library/types.html#types.prepare_class) обеспечивают поддержку создания динамических типов, соответствующих [**PEP 3115**](https://python-all.ru/3.9/whatsnew/3.3.html). ([bpo-14588](https://python-all.ru/3.9/whatsnew/3.3.html))

### unittest

[`assertRaises()`](https://python-all.ru/3.9/library/unittest.html#unittest.TestCase.assertRaises), [`assertRaisesRegex()`](https://python-all.ru/3.9/library/unittest.html#unittest.TestCase.assertRaisesRegex), [`assertWarns()`](https://python-all.ru/3.9/library/unittest.html#unittest.TestCase.assertWarns) и [`assertWarnsRegex()`](https://python-all.ru/3.9/library/unittest.html#unittest.TestCase.assertWarnsRegex) теперь принимают именованный аргумент *msg* при использовании в качестве менеджеров контекста. (Добавлено Эцио Мелотти и Уинстоном Эвертом в [bpo-10775](https://python-all.ru/3.9/whatsnew/3.3.html).)

[`unittest.TestCase.run()`](https://python-all.ru/3.9/library/unittest.html#unittest.TestCase.run) теперь возвращает [`TestResult`](https://python-all.ru/3.9/library/unittest.html#unittest.TestResult) объект.

### urllib

Класс [`Request`](https://python-all.ru/3.9/library/urllib.request.html#urllib.request.Request) теперь принимает аргумент *method*, используемый [`get_method()`](https://python-all.ru/3.9/library/urllib.request.html#urllib.request.Request.get_method) для определения того, какой HTTP-метод должен использоваться. Например, это отправит `'HEAD'` запрос:

```python
>>> urlopen(Request('https://www.python.org', method='HEAD'))
```

([bpo-1673007](https://python-all.ru/3.9/whatsnew/3.3.html))

### webbrowser

Модуль [`webbrowser`](https://python-all.ru/3.9/library/webbrowser.html#module-webbrowser) поддерживает больше «браузеров»: Google Chrome (называется **chrome**, **chromium**, **chrome-browser** или **chromium-browser** в зависимости от версии и операционной системы), и универсальные запускатели **xdg-open** из проекта FreeDesktop.org и **gvfs-open**, который является обработчиком URI по умолчанию для GNOME 3. (Первый добавлен Арно Кальметтом в [bpo-13620](https://python-all.ru/3.9/whatsnew/3.3.html), второй Маттиасом Клозе в [bpo-14493](https://python-all.ru/3.9/whatsnew/3.3.html).)

### xml.etree.ElementTree

Модуль [`xml.etree.ElementTree`](https://python-all.ru/3.9/library/xml.etree.elementtree.html#module-xml.etree.ElementTree) теперь импортирует своё C-ускорение по умолчанию; больше нет необходимости явно импортировать `xml.etree.cElementTree` (этот модуль остаётся для обратной совместимости, но теперь устарел). Кроме того, семейство методов `iter` [`Element`](https://python-all.ru/3.9/library/xml.etree.elementtree.html#xml.etree.ElementTree.Element) было оптимизировано (переписано на C). Документация модуля также была значительно улучшена: добавлены примеры и более подробная справочная информация.

### zlib

Новый атрибут [`zlib.Decompress.eof`](https://python-all.ru/3.9/library/zlib.html#zlib.Decompress.eof) позволяет различать правильно сформированный сжатый поток и неполный или обрезанный. (Добавлено Надимом Вавдой в [bpo-12646](https://python-all.ru/3.9/whatsnew/3.3.html).)

Новый атрибут [`zlib.ZLIB_RUNTIME_VERSION`](https://python-all.ru/3.9/library/zlib.html#zlib.ZLIB_RUNTIME_VERSION) сообщает строку версии базовой библиотеки `zlib`, загруженной во время выполнения. (Добавлено Торстеном Ландшоффом в [bpo-12306](https://python-all.ru/3.9/whatsnew/3.3.html).)

## Оптимизации

Добавлены значительные улучшения производительности:

- Благодаря [**PEP 393**](https://python-all.ru/3.9/whatsnew/3.3.html) некоторые операции над строками Unicode были оптимизированы:

  - объём памяти уменьшается в 2–4 раза в зависимости от текста
  - кодирование строки ASCII в UTF-8 больше не требует кодирования символов, представление UTF-8 совпадает с представлением ASCII
  - кодировщик UTF-8 был оптимизирован
  - повторение одного символа ASCII и получение подстроки ASCII-строки выполняется в 4 раза быстрее
- UTF-8 теперь работает в 2–4 раза быстрее. Кодирование UTF-16 теперь до 10 раз быстрее.

  (Автор – Serhiy Storchaka, [bpo-14624](https://python-all.ru/3.9/whatsnew/3.3.html), [bpo-14738](https://python-all.ru/3.9/whatsnew/3.3.html) и [bpo-15026](https://python-all.ru/3.9/whatsnew/3.3.html).)

## Изменения в сборке и C API

Изменения процесса сборки Python и C API включают:

- Новая функция, связанная с [**PEP 3118**](https://python-all.ru/3.9/whatsnew/3.3.html):

  - [`PyMemoryView_FromMemory()`](https://python-all.ru/3.9/c-api/memoryview.html#c.PyMemoryView_FromMemory)
- [**PEP 393**](https://python-all.ru/3.9/whatsnew/3.3.html) добавил новые типы, макросы и функции Unicode:

  - API высокого уровня:

    - [`PyUnicode_CopyCharacters()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_CopyCharacters)
    - [`PyUnicode_FindChar()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_FindChar)
    - [`PyUnicode_GetLength()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_GetLength), [`PyUnicode_GET_LENGTH`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_GET_LENGTH)
    - [`PyUnicode_New()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_New)
    - [`PyUnicode_Substring()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_Substring)
    - [`PyUnicode_ReadChar()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_ReadChar), [`PyUnicode_WriteChar()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_WriteChar)
  - API низкого уровня:

    - типы [`Py_UCS1`](https://python-all.ru/3.9/c-api/unicode.html#c.Py_UCS1), [`Py_UCS2`](https://python-all.ru/3.9/c-api/unicode.html#c.Py_UCS2), [`Py_UCS4`](https://python-all.ru/3.9/c-api/unicode.html#c.Py_UCS4)
    - структуры [`PyASCIIObject`](https://python-all.ru/3.9/c-api/unicode.html#c.PyASCIIObject) и [`PyCompactUnicodeObject`](https://python-all.ru/3.9/c-api/unicode.html#c.PyCompactUnicodeObject)
    - [`PyUnicode_READY`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_READY)
    - [`PyUnicode_FromKindAndData()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_FromKindAndData)
    - [`PyUnicode_AsUCS4()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_AsUCS4), [`PyUnicode_AsUCS4Copy()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_AsUCS4Copy)
    - [`PyUnicode_DATA`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_DATA), [`PyUnicode_1BYTE_DATA`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_1BYTE_DATA), [`PyUnicode_2BYTE_DATA`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_2BYTE_DATA), [`PyUnicode_4BYTE_DATA`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_4BYTE_DATA)
    - [`PyUnicode_KIND`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_KIND) с перечислением `PyUnicode_Kind`: [`PyUnicode_WCHAR_KIND`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_WCHAR_KIND), [`PyUnicode_1BYTE_KIND`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_1BYTE_KIND), [`PyUnicode_2BYTE_KIND`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_2BYTE_KIND), [`PyUnicode_4BYTE_KIND`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_4BYTE_KIND)
    - [`PyUnicode_READ`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_READ), [`PyUnicode_READ_CHAR`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_READ_CHAR), [`PyUnicode_WRITE`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_WRITE)
    - [`PyUnicode_MAX_CHAR_VALUE`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_MAX_CHAR_VALUE)
- [`PyArg_ParseTuple`](https://python-all.ru/3.9/c-api/arg.html#c.PyArg_ParseTuple) теперь принимает [`bytearray`](https://python-all.ru/3.9/library/stdtypes.html#bytearray) для формата `c` ([bpo-12380](https://python-all.ru/3.9/whatsnew/3.3.html)).

## Устарело

### Неподдерживаемые операционные системы

OS/2 и VMS больше не поддерживаются из-за отсутствия сопровождающего.

Windows 2000 и платформы Windows, для которых `COMSPEC` равно `command.com`, больше не поддерживаются из-за издержек на сопровождение.

Поддержка OSF, объявленная устаревшей в версии 3.2, полностью удалена.

### Устаревшие модули, функции и методы Python

- Передача непустой строки в `object.__format__()` объявлена устаревшей и в Python 3.4 будет приводить к [`TypeError`](https://python-all.ru/3.9/library/exceptions.html#TypeError) ([bpo-9856](https://python-all.ru/3.9/whatsnew/3.3.html)).
- Кодек `unicode_internal` объявлен устаревшим из-за [**PEP 393**](https://python-all.ru/3.9/whatsnew/3.3.html); используйте UTF-8, UTF-16 (`utf-16-le` или `utf-16-be`) или UTF-32 (`utf-32-le` или `utf-32-be`)
- [`ftplib.FTP.nlst()`](https://python-all.ru/3.9/library/ftplib.html#ftplib.FTP.nlst) и [`ftplib.FTP.dir()`](https://python-all.ru/3.9/library/ftplib.html#ftplib.FTP.dir): используйте [`ftplib.FTP.mlsd()`](https://python-all.ru/3.9/library/ftplib.html#ftplib.FTP.mlsd)
- `platform.popen()`: используйте модуль [`subprocess`](https://python-all.ru/3.9/library/subprocess.html#module-subprocess). Обратите особое внимание на раздел [Замена устаревших функций модулем subprocess](https://python-all.ru/3.9/library/subprocess.html#subprocess-replacements) ([bpo-11377](https://python-all.ru/3.9/whatsnew/3.3.html)).
- [bpo-13374](https://python-all.ru/3.9/whatsnew/3.3.html): API байтовых строк Windows объявлен устаревшим в модуле [`os`](https://python-all.ru/3.9/library/os.html#module-os). Используйте имена файлов в Unicode вместо байтовых имён, чтобы больше не зависеть от кодовой страницы ANSI и поддерживать любые имена файлов.
- [bpo-13988](https://python-all.ru/3.9/whatsnew/3.3.html): Модуль `xml.etree.cElementTree` объявлен устаревшим. Ускоритель используется автоматически, если доступен.
- Поведение `time.clock()` зависит от платформы: используйте новую функцию [`time.perf_counter()`](https://python-all.ru/3.9/library/time.html#time.perf_counter) или [`time.process_time()`](https://python-all.ru/3.9/library/time.html#time.process_time) в зависимости от ваших требований, чтобы получить чётко определённое поведение.
- Функция `os.stat_float_times()` объявлена устаревшей.
- Модуль [`abc`](https://python-all.ru/3.9/library/abc.html#module-abc):

  - [`abc.abstractproperty`](https://python-all.ru/3.9/library/abc.html#abc.abstractproperty) объявлен устаревшим, вместо него используйте [`property`](https://python-all.ru/3.9/library/functions.html#property) с [`abc.abstractmethod()`](https://python-all.ru/3.9/library/abc.html#abc.abstractmethod).
  - [`abc.abstractclassmethod`](https://python-all.ru/3.9/library/abc.html#abc.abstractclassmethod) объявлен устаревшим, вместо него используйте [`classmethod`](https://python-all.ru/3.9/library/functions.html#classmethod) с [`abc.abstractmethod()`](https://python-all.ru/3.9/library/abc.html#abc.abstractmethod).
  - [`abc.abstractstaticmethod`](https://python-all.ru/3.9/library/abc.html#abc.abstractstaticmethod) объявлен устаревшим, вместо него используйте [`staticmethod`](https://python-all.ru/3.9/library/functions.html#staticmethod) с [`abc.abstractmethod()`](https://python-all.ru/3.9/library/abc.html#abc.abstractmethod).
- Пакет [`importlib`](https://python-all.ru/3.9/library/importlib.html#module-importlib):

  - [`importlib.abc.SourceLoader.path_mtime()`](https://python-all.ru/3.9/library/importlib.html#importlib.abc.SourceLoader.path_mtime) теперь объявлен устаревшим в пользу [`importlib.abc.SourceLoader.path_stats()`](https://python-all.ru/3.9/library/importlib.html#importlib.abc.SourceLoader.path_stats), так как файлы байт-кода теперь хранят как время модификации, так и размер исходного файла, из которого был скомпилирован файл байт-кода.

### Устаревшие функции и типы C API

[`Py_UNICODE`](https://python-all.ru/3.9/c-api/unicode.html#c.Py_UNICODE) объявлен устаревшим согласно [**PEP 393**](https://python-all.ru/3.9/whatsnew/3.3.html) и будет удалён в Python 4. Все функции, использующие этот тип, объявлены устаревшими:

Функции и методы Unicode, использующие [`Py_UNICODE`](https://python-all.ru/3.9/c-api/unicode.html#c.Py_UNICODE) и [`Py_UNICODE*`](https://python-all.ru/3.9/c-api/unicode.html#c.Py_UNICODE) типы:

- [`PyUnicode_FromUnicode`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_FromUnicode): используйте [`PyUnicode_FromWideChar()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_FromWideChar) или [`PyUnicode_FromKindAndData()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_FromKindAndData)
- [`PyUnicode_AS_UNICODE`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_AS_UNICODE), [`PyUnicode_AsUnicode()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_AsUnicode), [`PyUnicode_AsUnicodeAndSize()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_AsUnicodeAndSize): используйте [`PyUnicode_AsWideCharString()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_AsWideCharString)
- [`PyUnicode_AS_DATA`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_AS_DATA): используйте [`PyUnicode_DATA`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_DATA) с [`PyUnicode_READ`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_READ) и [`PyUnicode_WRITE`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_WRITE)
- [`PyUnicode_GET_SIZE`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_GET_SIZE), [`PyUnicode_GetSize()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_GetSize): используйте [`PyUnicode_GET_LENGTH`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_GET_LENGTH) или [`PyUnicode_GetLength()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_GetLength)
- [`PyUnicode_GET_DATA_SIZE`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_GET_DATA_SIZE): используйте `PyUnicode_GET_LENGTH(str) * PyUnicode_KIND(str)` (работает только с готовыми строками)
- [`PyUnicode_AsUnicodeCopy()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_AsUnicodeCopy): используйте [`PyUnicode_AsUCS4Copy()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_AsUCS4Copy) или [`PyUnicode_AsWideCharString()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_AsWideCharString)
- `PyUnicode_GetMax()`

Функции и макросы для работы со строками Py\_UNICODE\*:

- `Py_UNICODE_strlen`: используйте [`PyUnicode_GetLength()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_GetLength) или [`PyUnicode_GET_LENGTH`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_GET_LENGTH)
- `Py_UNICODE_strcat`: используйте [`PyUnicode_CopyCharacters()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_CopyCharacters) или [`PyUnicode_FromFormat()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_FromFormat)
- `Py_UNICODE_strcpy`, `Py_UNICODE_strncpy`, `Py_UNICODE_COPY`: используйте [`PyUnicode_CopyCharacters()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_CopyCharacters) или [`PyUnicode_Substring()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_Substring)
- `Py_UNICODE_strcmp`: используйте [`PyUnicode_Compare()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_Compare)
- `Py_UNICODE_strncmp`: используйте [`PyUnicode_Tailmatch()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_Tailmatch)
- `Py_UNICODE_strchr`, `Py_UNICODE_strrchr`: используйте [`PyUnicode_FindChar()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_FindChar)
- `Py_UNICODE_FILL`: используйте [`PyUnicode_Fill()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_Fill)
- `Py_UNICODE_MATCH`

Кодировщики:

- [`PyUnicode_Encode()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_Encode): используйте `PyUnicode_AsEncodedObject()`
- [`PyUnicode_EncodeUTF7()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_EncodeUTF7)
- [`PyUnicode_EncodeUTF8()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_EncodeUTF8): используйте [`PyUnicode_AsUTF8()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_AsUTF8) или [`PyUnicode_AsUTF8String()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_AsUTF8String)
- [`PyUnicode_EncodeUTF32()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_EncodeUTF32)
- [`PyUnicode_EncodeUTF16()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_EncodeUTF16)
- [`PyUnicode_EncodeUnicodeEscape()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_EncodeUnicodeEscape) используйте [`PyUnicode_AsUnicodeEscapeString()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_AsUnicodeEscapeString)
- [`PyUnicode_EncodeRawUnicodeEscape()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_EncodeRawUnicodeEscape) используйте [`PyUnicode_AsRawUnicodeEscapeString()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_AsRawUnicodeEscapeString)
- [`PyUnicode_EncodeLatin1()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_EncodeLatin1): используйте [`PyUnicode_AsLatin1String()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_AsLatin1String)
- [`PyUnicode_EncodeASCII()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_EncodeASCII): используйте [`PyUnicode_AsASCIIString()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_AsASCIIString)
- [`PyUnicode_EncodeCharmap()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_EncodeCharmap)
- [`PyUnicode_TranslateCharmap()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_TranslateCharmap)
- [`PyUnicode_EncodeMBCS()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_EncodeMBCS): используйте [`PyUnicode_AsMBCSString()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_AsMBCSString) или [`PyUnicode_EncodeCodePage()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_EncodeCodePage) (с `CP_ACP` code\_page)
- `PyUnicode_EncodeDecimal()`, [`PyUnicode_TransformDecimalToASCII()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_TransformDecimalToASCII)

### Устаревшие возможности

Форматный код `'u'` модуля [`array`](https://python-all.ru/3.9/library/array.html#module-array) теперь устарел и будет удалён в Python 4 вместе с остальной частью API ([`Py_UNICODE`](https://python-all.ru/3.9/c-api/unicode.html#c.Py_UNICODE)).

## Переход на Python 3.3

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

### Портирование кода Python

- Рандомизация хеша включена по умолчанию. Установите переменную окружения [`PYTHONHASHSEED`](https://python-all.ru/3.9/using/cmdline.html#envvar-PYTHONHASHSEED) в `0`, чтобы отключить рандомизацию хеша. См. также метод [`object.__hash__()`](https://python-all.ru/3.9/reference/datamodel.html#object.__hash__).
- [bpo-12326](https://python-all.ru/3.9/whatsnew/3.3.html): В Linux sys.platform больше не содержит номер старшей версии. Теперь это всегда 'linux', вместо 'linux2' или 'linux3' в зависимости от версии Linux, использованной при сборке Python. Замените sys.platform == 'linux2' на sys.platform.startswith('linux') или просто sys.platform == 'linux', если не нужно поддерживать старые версии Python.
- [bpo-13847](https://python-all.ru/3.9/whatsnew/3.3.html), [bpo-14180](https://python-all.ru/3.9/whatsnew/3.3.html): [`time`](https://python-all.ru/3.9/library/time.html#module-time) и [`datetime`](https://python-all.ru/3.9/library/datetime.html#module-datetime): [`OverflowError`](https://python-all.ru/3.9/library/exceptions.html#OverflowError) теперь возбуждается вместо [`ValueError`](https://python-all.ru/3.9/library/exceptions.html#ValueError), если временная метка выходит за пределы диапазона. [`OSError`](https://python-all.ru/3.9/library/exceptions.html#OSError) теперь возбуждается, если функции C `gmtime()` или `localtime()` завершились ошибкой.
- Используемые по умолчанию искатели (finders) модуля import теперь используют кеш содержимого конкретного каталога. Если вы создаёте файл исходного кода Python или файл байт-кода без исходного кода, обязательно вызовите [`importlib.invalidate_caches()`](https://python-all.ru/3.9/library/importlib.html#importlib.invalidate_caches), чтобы очистить кеш, чтобы искатели заметили новый файл.
- [`ImportError`](https://python-all.ru/3.9/library/exceptions.html#ImportError) теперь использует полное имя модуля, который пытались импортировать. Доктесты, проверяющие сообщение об ошибке ImportError, нужно обновить, чтобы они использовали полное имя модуля вместо только последней части имени.
- Аргумент *index* функции [`__import__()`](https://python-all.ru/3.9/library/functions.html#__import__) теперь по умолчанию равен 0 вместо -1 и больше не поддерживает отрицательные значения. Это было упущением при реализации [**PEP 328**](https://python-all.ru/3.9/whatsnew/3.3.html), что значение по умолчанию осталось -1. Если нужно продолжать выполнять относительный импорт с последующим абсолютным, выполните относительный импорт с индексом 1, а затем ещё один импорт с индексом 0. Однако предпочтительнее использовать [`importlib.import_module()`](https://python-all.ru/3.9/library/importlib.html#importlib.import_module) вместо прямого вызова [`__import__()`](https://python-all.ru/3.9/library/functions.html#__import__).
- [`__import__()`](https://python-all.ru/3.9/library/functions.html#__import__) больше не позволяет использовать значение индекса, отличное от 0, для модулей верхнего уровня. Например, `__import__('sys', level=1)` теперь приводит к ошибке.
- Поскольку [`sys.meta_path`](https://python-all.ru/3.9/library/sys.html#sys.meta_path) и [`sys.path_hooks`](https://python-all.ru/3.9/library/sys.html#sys.path_hooks) теперь по умолчанию содержат искатели (finders), скорее всего, для добавления в эти списки вам потребуется использовать `list.insert()` вместо `list.append()`.
- Поскольку `None` теперь вставляется в [`sys.path_importer_cache`](https://python-all.ru/3.9/library/sys.html#sys.path_importer_cache), при очистке записей словаря путей, не имеющих искателя, потребуется удалять ключи, связанные со значениями `None` **и** [`imp.NullImporter`](https://python-all.ru/3.9/library/imp.html#imp.NullImporter), чтобы сохранить обратную совместимость. Это приведёт к дополнительным накладным расходам в старых версиях Python, которые повторно вставляют `None` в [`sys.path_importer_cache`](https://python-all.ru/3.9/library/sys.html#sys.path_importer_cache), где он представляет использование неявных искателей, но семантически это ничего не должно изменить.
- [`importlib.abc.Finder`](https://python-all.ru/3.9/library/importlib.html#importlib.abc.Finder) больше не требует реализации абстрактного метода *find\_module()*. Если вы полагались на то, что подклассы реализуют этот метод, сначала убедитесь в его существовании. Вероятно, вам стоит сначала проверить *find\_loader()*, если вы работаете с [искателями записей пути](https://python-all.ru/3.9/glossary.html#term-path-entry-finder).
- [`pkgutil`](https://python-all.ru/3.9/library/pkgutil.html#module-pkgutil) переведён на внутреннее использование [`importlib`](https://python-all.ru/3.9/library/importlib.html#module-importlib). Это устраняет множество граничных случаев, в которых старый режим эмуляции импорта [**PEP 302**](https://python-all.ru/3.9/whatsnew/3.3.html) не соответствовал поведению реальной системы импорта. Сама эмуляция импорта всё ещё присутствует, но теперь считается устаревшей. Функции [`pkgutil.iter_importers()`](https://python-all.ru/3.9/library/pkgutil.html#pkgutil.iter_importers) и [`pkgutil.walk_packages()`](https://python-all.ru/3.9/library/pkgutil.html#pkgutil.walk_packages) обрабатывают стандартные хуки импорта как особый случай, поэтому они по-прежнему поддерживаются, хотя и не предоставляют нестандартный метод `iter_modules()`.
- Исправлена давняя ошибка соответствия RFC ([bpo-1079](https://python-all.ru/3.9/whatsnew/3.3.html)) в синтаксическом анализе, выполняемом [`email.header.decode_header()`](https://python-all.ru/3.9/library/email.header.html#email.header.decode_header). Код, использующий стандартную идиому преобразования закодированных заголовков в Unicode (`str(make_header(decode_header(h))`), не изменится, но код, анализирующий отдельные кортежи, возвращаемые decode\_header, заметит, что пробелы, предшествующие или следующие за разделами `ASCII`, теперь включаются в раздел `ASCII`. Код, создающий заголовки с помощью `make_header`, также должен продолжать работать без изменений, поскольку `make_header` по-прежнему добавляет пробелы между разделами `ASCII` и не-`ASCII`, если их ещё нет во входных строках.
- [`email.utils.formataddr()`](https://python-all.ru/3.9/library/email.utils.html#email.utils.formataddr) теперь выполняет правильную кодировку передачи содержимого для отображаемых имён, не являющихся `ASCII`. Любой код, который полагался на предыдущее ошибочное поведение, сохранявшее не-`ASCII` юникод в форматированной выходной строке, потребуется изменить ([bpo-1690608](https://python-all.ru/3.9/whatsnew/3.3.html)).
- [`poplib.POP3.quit()`](https://python-all.ru/3.9/library/poplib.html#poplib.POP3.quit) теперь может вызывать ошибки протокола, как и все остальные методы `poplib`. Код, предполагающий, что `quit` не вызывает ошибок [`poplib.error_proto`](https://python-all.ru/3.9/library/poplib.html#poplib.error_proto), возможно, потребуется изменить, если в конкретном приложении возникнут ошибки на `quit` ([bpo-11291](https://python-all.ru/3.9/whatsnew/3.3.html)).
- Аргумент `strict` функции [`email.parser.Parser`](https://python-all.ru/3.9/library/email.parser.html#email.parser.Parser), устаревший начиная с Python 2.4, наконец удалён.
- Устаревший метод `unittest.TestCase.assertSameElements` удалён.
- Устаревшая переменная `time.accept2dyear` удалена.
- Устаревший атрибут `Context._clamp` удалён из модуля [`decimal`](https://python-all.ru/3.9/library/decimal.html#module-decimal). Ранее он был заменён публичным атрибутом `clamp`. (См. [bpo-8540](https://python-all.ru/3.9/whatsnew/3.3.html).)
- Незадокументированный внутренний вспомогательный класс `SSLFakeFile` удалён из [`smtplib`](https://python-all.ru/3.9/library/smtplib.html#module-smtplib), поскольку его функциональность давно напрямую предоставляется [`socket.socket.makefile()`](https://python-all.ru/3.9/library/socket.html#socket.socket.makefile).
- Передача отрицательного значения в [`time.sleep()`](https://python-all.ru/3.9/library/time.html#time.sleep) в Windows теперь вызывает ошибку вместо бесконечного ожидания. В POSIX это всегда вызывало ошибку.
- Константа `ast.__version__` удалена. Если нужно принимать решения, зависящие от версии AST, используйте для этого [`sys.version_info`](https://python-all.ru/3.9/library/sys.html#sys.version_info).
- Коду, который обходил тот факт, что модуль [`threading`](https://python-all.ru/3.9/library/threading.html#module-threading) использовал фабричные функции, путём наследования от приватных классов, потребуется измениться, чтобы наследовать теперь уже публичные классы.
- Незадокументированный отладочный механизм в модуле threading удалён, что упростило код. Это не должно повлиять на production-код, но упоминается здесь на случай, если какие-либо отладочные фреймворки приложений с ним взаимодействовали ([bpo-13550](https://python-all.ru/3.9/whatsnew/3.3.html)).

### Перенос кода на C

- В ходе изменений API буферов недокументированный член `smalltable` структуры [`Py_buffer`](https://python-all.ru/3.9/c-api/buffer.html#c.Py_buffer) был удалён, а структура `PyMemoryViewObject` изменена.

  Все расширения, зависящие от соответствующих частей в `memoryobject.h` или `object.h`, должны быть пересобраны.
- В связи с [PEP 393](https://python-all.ru/3.9/whatsnew/3.3.html#pep-393) тип [`Py_UNICODE`](https://python-all.ru/3.9/c-api/unicode.html#c.Py_UNICODE) и все функции, использующие этот тип, объявлены устаревшими (но останутся доступными как минимум на пять лет). Если вы использовали низкоуровневые Unicode API для создания и доступа к объектам unicode и хотите воспользоваться уменьшением потребления памяти, обеспечиваемым [**PEP 393**](https://python-all.ru/3.9/whatsnew/3.3.html), вам нужно перевести свой код на новый [Unicode API](https://python-all.ru/3.9/c-api/unicode.html).

  Однако, если вы использовали только высокоуровневые функции, такие как [`PyUnicode_Concat()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_Concat), [`PyUnicode_Join()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_Join) или [`PyUnicode_FromFormat()`](https://python-all.ru/3.9/c-api/unicode.html#c.PyUnicode_FromFormat), ваш код автоматически воспользуется преимуществами новых представлений Unicode.
- [`PyImport_GetMagicNumber()`](https://python-all.ru/3.9/c-api/import.html#c.PyImport_GetMagicNumber) теперь возвращает `-1` в случае неудачи.
- Поскольку отрицательное значение аргумента *level* для [`__import__()`](https://python-all.ru/3.9/library/functions.html#__import__) больше недопустимо, то же самое теперь относится и к [`PyImport_ImportModuleLevel()`](https://python-all.ru/3.9/c-api/import.html#c.PyImport_ImportModuleLevel). Это также означает, что значение *level*, используемое [`PyImport_ImportModuleEx()`](https://python-all.ru/3.9/c-api/import.html#c.PyImport_ImportModuleEx), теперь равно `0` вместо `-1`.

### Сборка расширений C

- Диапазон возможных имён файлов для расширений C сужен. Очень редко используемые варианты написания были отключены: в POSIX файлы с именами `xxxmodule.so`, `xxxmodule.abi3.so` и `xxxmodule.cpython-*.so` больше не распознаются как реализующие модуль `xxx`. Если вы создавали такие файлы, вам нужно перейти на другие варианты написания (т.е. удалить строку `module` из имён файлов).

  (реализовано в [bpo-14040](https://python-all.ru/3.9/whatsnew/3.3.html).)

### Изменения параметров командной строки

- Флаг командной строки -Q и связанные с ним артефакты удалены. Код, проверяющий sys.flags.division\_warning, потребует обновления.

  ([bpo-10998](https://python-all.ru/3.9/whatsnew/3.3.html), предоставлено Эриком Араужо.)
- Когда **python** запускается с [`-S`](https://python-all.ru/3.9/using/cmdline.html#id3), `import site` больше не будет добавлять пути, специфичные для сайта, в пути поиска модулей. В предыдущих версиях это делалось.

  ([bpo-11591](https://python-all.ru/3.9/whatsnew/3.3.html), предоставлен Карлом Мейером с правками Эрика Араужо.)
