Что нового в Python 3.2

Автор:Рэймонд Хеттингер

В этой статье объясняются новые возможности Python 3.2 по сравнению с 3.1. Он фокусируется на нескольких основных моментах и предоставляет несколько примеров. Полную информацию см. в файле Misc/NEWS.

См.также

PEP 392 — Расписание релиза Python 3.2

PEP 384: Определение стабильного ABI

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

С Python 3.2 становится доступным альтернативный подход: модули расширения, ограничивающие себя ограниченным API (путём определения Py_LIMITED_API), не могут использовать многие внутренние компоненты, но ограничены набором функций API, обещающие быть стабильными для нескольких релизов. Как следствие, модули расширения, созданные для версии 3.2 в этом режиме, также будут работать с версиями 3.3, 3.4 и т. д. Модули расширения, использующие детали структур памяти, всё ещё могут быть построены, но их необходимо будет перекомпилировать для каждого релиза функции.

См.также

PEP 384 — Определение стабильного ABI
PEP, написанный Мартином фон Лёвисом.

PEP 389: модуль парсинга командной строки argparse

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

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

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

import argparse
parser = argparse.ArgumentParser(
            description = 'Manage servers',         # основное описание для справки
            epilog = 'Tested on Solaris and Linux') # отображается после справки
parser.add_argument('action',                       # имя аргумента
            choices = ['deploy', 'start', 'stop'],  # три допустимых значения
            help = 'action on each target')         # сообщение помощи
parser.add_argument('targets',
            metavar = 'HOSTNAME',                   # имя переменной, используемое в справке msg
            nargs = '+',                            # требуется одна или несколько целей
            help = 'url for target machines')       # справочное сообщение с объяснением
parser.add_argument('-u', '--user',                 # -u или --user опция
            required = True,                        # сделает его обязательным аргументом
            help = 'login as user')

Пример вызова парсера из командной строки:

>>> cmd = 'deploy sneezy.example.com sleepy.example.com -u skycaptain'
>>> result = parser.parse_args(cmd.split())
>>> result.action
'deploy'
>>> result.targets
['sneezy.example.com', 'sleepy.example.com']
>>> result.user
'skycaptain'

Пример автоматически сгенерированной справки парсера:

>>> parser.parse_args('-h'.split())

usage: manage_cloud.py [-h] -u USER
                       {deploy,start,stop} HOSTNAME [HOSTNAME ...]

Manage servers

positional arguments:
  {deploy,start,stop}   action on each target
  HOSTNAME              url for target machines

optional arguments:
  -h, --help            show this help message and exit
  -u USER, --user USER  login as user

Tested on Solaris and Linux

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

import argparse
parser = argparse.ArgumentParser(prog='HELM')
subparsers = parser.add_subparsers()

parser_l = subparsers.add_parser('launch', help='Launch Control')   # первая подгруппа
parser_l.add_argument('-m', '--missiles', action='store_true')
parser_l.add_argument('-t', '--torpedos', action='store_true')

parser_m = subparsers.add_parser('move', help='Move Vessel',        # вторая подгруппа
                                 aliases=('steer', 'turn'))         # эквивалентные имена
parser_m.add_argument('-c', '--course', type=int, required=True)
parser_m.add_argument('-s', '--speed', type=int, default=0)
$ ./helm.py --help                         # справка верхнего уровня (запуск и перемещение)
$ ./helm.py launch --help                  # справка по параметрам запуска
$ ./helm.py launch --missiles              # установка missiles=True и torpedos=False
$ ./helm.py steer --course 180 --speed 5   # установка movement параметра

См.также

PEP 389 — Новый модуль парсинга командной строки
PEP, написанный Стивеном Бетардом.

Обновление кода optparse для получения подробной информации об отличиях от optparse.

PEP 391: Конфигурация на основе словаря для логгирования

Модуль logging предоставляет два типа конфигурации: один стиль с вызовами функций для каждого параметра или другой стиль, управляемый внешним файлом, сохранённым в формате ConfigParser. Данные параметры не обеспечивали гибкости для создания конфигураций из файлов JSON или YAML, а также не поддерживали добавочную конфигурацию, которая необходима для указания параметров логгера из командной строки.

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

{"version": 1,
 "formatters": {"brief": {"format": "%(levelname)-8s: %(name)-15s: %(message)s"},
                "full": {"format": "%(asctime)s %(name)-15s %(levelname)-8s %(message)s"}
                },
 "handlers": {"console": {
                   "class": "logging.StreamHandler",
                   "formatter": "brief",
                   "level": "INFO",
                   "stream": "ext://sys.stdout"},
              "console_priority": {
                   "class": "logging.StreamHandler",
                   "formatter": "full",
                   "level": "ERROR",
                   "stream": "ext://sys.stderr"}
              },
 "root": {"level": "DEBUG", "handlers": ["console", "console_priority"]}}

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

>>> import json, logging.config
>>> with open('conf.json') as f:
...     conf = json.load(f)
...
>>> logging.config.dictConfig(conf)
>>> logging.info("Transaction completed normally")
INFO    : root           : Transaction completed normally
>>> logging.critical("Abnormal termination")
2011-02-17 11:14:36,694 root            CRITICAL Abnormal termination

См.также

PEP 391 — конфигурация для ведения журнала на основе словаря
PEP, написанный Винаем Саджипом.

PEP 3148: модуль concurrent.futures

Код для создания параллелизма и управления им собирается в новом пространстве имён верхнего уровня concurrent. Его первым элементом является пакет futures, предоставляющий единый высокоуровневый интерфейс для управления потоками и процессами.

Дизайн concurrent.futures был вдохновлен пакетом java.util.concurrent. В этой модели выполняемый вызов и его результат представлены объектом Future, который абстрагирует функции, общие для потоков, процессов и удалённых вызовов процедур. Данный объект поддерживает проверки состояния (выполняется или выполнено), тайм-ауты, отмены, добавление обратных вызовов и доступ к результатам или исключениям.

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

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

Оба класса имеют общий интерфейс с тремя методами: submit() для планирования вызываемого объекта и возврата объекта Future; map() для планирования множества асинхронных вызовов за раз и shutdown() для освобождения ресурсов. Класс представляет собой контекстный менеджер и может использоваться в операторе with, чтобы гарантировать, что ресурсы автоматически освобождаются, когда в настоящее время ожидающие футуры выполняются.

Простой пример ThreadPoolExecutor — запуск четырёх параллельных потоков для копирования файлов:

import concurrent.futures, shutil
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as e:
    e.submit(shutil.copy, 'src1.txt', 'dest1.txt')
    e.submit(shutil.copy, 'src2.txt', 'dest2.txt')
    e.submit(shutil.copy, 'src3.txt', 'dest3.txt')
    e.submit(shutil.copy, 'src3.txt', 'dest4.txt')

См.также

PEP 3148 — Futures — асинхронное выполнение вычислений
PEP, написанный Брайаном Куинланом.

Код для многопоточного параллельного чтения URL-адресов — пример использования потоков для параллельной выборки нескольких веб-страниц.

Код для параллельного вычисления простых чисел, пример, демонстрирующий ProcessPoolExecutor.

PEP 3147: Каталоги PYC репозиториев

Схема Python для кэширования байт-кода в файлах .pyc плохо работала в средах с несколькими интерпретаторами Python. Если один интерпретатор столкнулся с кэшированным файлом, созданным другим интерпретатором, он перекомпилировал исходный код и перезаписал кэшированный файл, тем самым потеряв преимущества кэширования.

Проблема «драки pyc» стала более заметной, поскольку для дистрибутивов Linux стало обычным делом поставляться с несколькими версиями Python. Данные конфликты также возникают с альтернативами CPython, такими как Unladen Swallow.

Чтобы решить эту проблему, механизм импорта Python был расширен для использования разных имён файлов для каждого интерпретатора. Вместо Python 3.2, Python 3.3 и Unladen Swallow, каждый из которых конкурирует за файл с именем «mymodule.pyc», теперь они будут искать «mymodule.cpython-32.pyc», «mymodule.cpython-33.pyc» и «mymodule .unladen10.pyc«. И чтобы все данные новые файлы не загромождали исходные каталоги, файлы pyc теперь собраны в каталоге «__pycache__», хранящемся в каталоге пакета.

Помимо имён файлов и целевых каталогов, новая схема имеет несколько аспектов, видимых программисту:

  • Импортированные модули теперь имеют атрибут __cached__, в котором хранится имя фактического импортированного файла:

    >>> import collections
    >>> collections.__cached__ # doctest: +SKIP
    'c:/py32/lib/__pycache__/collections.cpython-32.pyc'
    
  • Тег, уникальный для каждого интерпретатора, доступен из файла imp модуля:

    >>> import imp
    >>> imp.get_tag() # doctest: +SKIP
    'cpython-32'
    
  • Скрипты, которые пытаются вывести имя исходного файла из импортированного файла, теперь должны быть умнее. Уже недостаточно просто удалить «c» из имени файла «.pyc». Вместо этого используйте новые функции в модуле imp:

    >>> imp.source_from_cache('c:/py32/lib/__pycache__/collections.cpython-32.pyc')
    'c:/py32/lib/collections.py'
    >>> imp.cache_from_source('c:/py32/lib/collections.py') # doctest: +SKIP
    'c:/py32/lib/__pycache__/collections.cpython-32.pyc'
    
  • Модули py_compile и compileall были обновлены, чтобы отразить новое соглашение об именах и целевой каталог. Вызов compileall из командной строки имеет новые параметры: -i для указания списка файлов и каталогов для компиляции и -b, который заставляет файлы байт-кода записываться в их устаревшее местоположение, а не в __pycache__.

  • Модуль importlib.abc был обновлён новым абстрактным базовым классом для загрузки файлов байт-кода. Устаревшие ABC, PyLoader и PyPycLoader, объявлены устаревшими (инструкции по сохранению совместимости с Python 3.1 включены в документацию).

См.также

PEP 3147 — Каталоги репозиториев PYC
PEP, написанный Барри Варшавой.

PEP 3149: файлы версии ABI с тегами .so

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

Общий каталог является «pyshared», а имена файлов различаются за счёт идентификации реализации Python (например, CPython, PyPy, Jython и т. д.), основного и дополнительного номеров версий и необязательных флагов сборки (например, «d» для debug, «m» для pymalloc, «u» для широкого юникода). Для произвольного пакета «foo» вы можете увидеть данные файлы при установке дистрибутива:

/usr/share/pyshared/foo.cpython-32m.so
/usr/share/pyshared/foo.cpython-33md.so

В самом Python теги доступны из функций в файле sysconfig модуля:

>>> import sysconfig
>>> sysconfig.get_config_var('SOABI')       # найти тег версии
'cpython-32mu'
>>> sysconfig.get_config_var('EXT_SUFFIX')  # найти полное расширение имени файла
'.cpython-32mu.so'

См.также

PEP 3149 — файлы версии ABI с тегами .so
PEP, написанный Барри Варшавой.

PEP 3333: Интерфейс шлюза веб-сервера Python v1.0.1

Данный информационный PEP поясняет, как протокол WSGI должен обрабатывать проблемы с байтами/текстом. Проблема заключается в том, что обработка строк в Python 3 наиболее удобна для обработки с типом str, хотя сам протокол HTTP ориентирован на байты.

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

У родных строк всегда тип str, но ограничены кодовыми точками от U+0000 до U+00FF, которые можно преобразовать в байты с использованием кодировки Latin-1. Данные строки используются для ключей и значений в словаре среды, а также для заголовков ответов и состояний в функции start_response(). Они должны соответствовать кодировке RFC 2616. Т. е. они должны быть либо символами ISO-8859-1, либо использовать кодировку MIME RFC 2047.

Для разработчиков, переносящих приложения WSGI из Python 2, вот важные моменты:

  • Если приложение уже использовало строки для заголовков в Python 2, никаких изменений не требуется.
  • Если вместо этого приложение закодировало выходные заголовки или декодировало входные заголовки, то заголовки необходимо будет перекодировать в Latin-1. Например, выходной заголовок, закодированный в utf-8, использовал h.encode('utf-8'), теперь необходимо преобразовать байты в собственные строки, используя h.encode('utf-8').decode('latin-1').
  • Значения, полученные приложением или отправленные с использованием метода write(), должны быть строками байтов. Функция и среда start_response() должны использовать собственные строки. Два нельзя смешивать.

Для разработчиков серверов, пишущих пути CGI-to-WSGI или другие протоколы в стиле CGI, пользователи должны иметь возможность доступа к среде с использованием собственных строк, даже если базовая платформа может иметь другое соглашение. Чтобы восполнить данный пробел, модуль wsgiref имеет новую функцию wsgiref.handlers.read_environ() для перекодирования переменных CGI из os.environ в исходные строки и возврата нового словаря.

См.также

PEP 3333 — Интерфейс шлюза веб-сервера Python версии 1.0.1
PEP, написанный Филиппом Эби.

Другие языковые изменения

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

  • Форматирование строк для format() и str.format() получило новые возможности для символа формата #. Раньше для целых чисел в двоичном, восьмеричном или шестнадцатеричном формате вывод ставился с префиксом «0b», «0o» или «0x» соответственно. Теперь он также может обрабатывать числа с плавающей запятой, сложные и десятичные числа, в результате чего на выходе всегда будет десятичная точка, даже если за ней не следуют цифры.

    >>> format(20, '#o')
    '0o24'
    >>> format(12.34, '#5.0f')
    '  12.'
    

    (Предложено Марком Дикинсоном и реализовано Эриком Смитом в bpo-7094.)

  • Существует также новый метод str.format_map(), который расширяет возможности существующего метода str.format(), принимая произвольные объекты отображения. Данный новый метод позволяет использовать форматирование строк с любым из многих словарных объектов Python, например, defaultdict, Shelf, ConfigParser или dbm. Это также полезно с пользовательскими подклассами dict, которые нормализуют ключи перед поиском или предоставляют метод __missing__() для неизвестных ключей:

    >>> import shelve
    >>> d = shelve.open('tmp.shl')
    >>> 'The {project_name} status is {status} as of {date}'.format_map(d)
    'The testing project status is green as of February 15, 2011'
    
    >>> class LowerCasedDict(dict):
    ...     def __getitem__(self, key):
    ...         return dict.__getitem__(self, key.lower())
    >>> lcd = LowerCasedDict(part='widgets', quantity=10)
    >>> 'There are {QUANTITY} {Part} in stock'.format_map(lcd)
    'There are 10 widgets in stock'
    
    >>> class PlaceholderDict(dict):
    ...     def __missing__(self, key):
    ...         return '<{}>'.format(key)
    >>> 'Hello {name}, welcome to {location}'.format_map(PlaceholderDict())
    'Hello <name>, welcome to <location>'
    

(Предложено Рэймондом Хеттингером и реализовано Эриком Смитом в bpo-6081.)

  • Теперь интерпретатор можно запустить с тихой опцией -q, чтобы предотвратить отображение информации об авторских правах и версии в интерактивном режиме. Опцию можно проверить с помощью атрибута sys.flags:

    $ python -q
    >>> sys.flags
    sys.flags(debug=0, division_warning=0, inspect=0, interactive=0,
    optimize=0, dont_write_bytecode=0, no_user_site=0, no_site=0,
    ignore_environment=0, verbose=0, bytes_warning=0, quiet=1)
    

    (Предоставлено Марцином Войдиром в bpo-1772833).

  • Функция hasattr() работает, вызывая getattr() и определяя, возникает ли исключение. Данный метод позволяет ему обнаруживать методы, созданные динамически с помощью __getattr__() или __getattribute__(), которые в противном случае отсутствовали бы в словаре классов. Раньше hasattr перехватывал любые исключения, возможно, маскируя подлинные ошибки. Теперь hasattr был ужесточен, чтобы перехватывать только AttributeError и пропускать другие исключения:

    >>> class A:
    ...     @property
    ...     def f(self):
    ...         return 1 // 0
    ...
    >>> a = A()
    >>> hasattr(a, 'f')
    Traceback (most recent call last):
      ...
    ZeroDivisionError: integer division or modulo by zero
    

    (Обнаружен Юрием Селивановым и исправлен Бенджамином Петерсоном; bpo-9666.)

  • str() числа с плавающей запятой или комплексного числа теперь совпадает с его repr(). Раньше форма str() была короче, но это только вызывало путаницу, и теперь она больше не нужна, поскольку по умолчанию отображается самая короткая repr():

    >>> import math
    >>> repr(math.pi)
    '3.141592653589793'
    >>> str(math.pi)
    '3.141592653589793'
    

    (Предложено и реализовано Марком Дикинсоном; bpo-9337.)

  • Объекты memoryview теперь имеют метод release(), а также поддерживают протокол управления контекстом. Это позволяет своевременно освобождать любые ресурсы, которые были получены при запросе буфера из исходного объекта.

    >>> with memoryview(b'abcdefgh') as v:
    ...     print(v.tolist())
    [97, 98, 99, 100, 101, 102, 103, 104]
    

    (Добавлено Антуаном Питру; bpo-9757.)

  • Ранее было запрещено удалять имя из локального пространства имён, если оно встречается как свободная переменная во вложенном блоке:

    def outer(x):
        def inner():
            return x
        inner()
        del x
    

    Теперь это разрешено. Помните, что цель предложения except очищена, поэтому данный код, который раньше работал с Python 2.6, поднял SyntaxError с Python 3.1 и теперь снова работает:

    def f():
        def print_error():
            print(e)
        try:
            something
        except Exception as e:
            print_error()
            # неявное "del e" здесь
    

    (См. bpo-4617.)

  • Внутренний инструмент structsequence теперь создаёт подклассы кортежа. Это означает, что C структуры, подобные возвращаемые os.stat(), time.gmtime() и sys.version_info, теперь работают как именованный кортеж и теперь работают с функциями и методами, ожидающие кортеж в качестве аргумента. Это большой шаг вперед в том, чтобы сделать структуры C такими же гибкими, как их аналоги на чистом Python:

    >>> import sys
    >>> isinstance(sys.version_info, tuple)
    True
    >>> 'Version %d.%d.%d %s(%d)' % sys.version_info # doctest: +SKIP
    'Version 3.2.0 final(0)'
    

    (Предложено Арфревером Фрехтесом Тайферсаром Арахесисом и реализовано Бенджамином Петерсоном в bpo-8413.)

  • Предупреждениями теперь легче управлять с помощью переменной среды PYTHONWARNINGS в качестве альтернативы использованию -W в командной строке:

    $ export PYTHONWARNINGS='ignore::RuntimeWarning::,once::UnicodeWarning::'
    

    (Предложено Барри Варшавой и реализовано Филипом Дженви в bpo-7301.)

  • Добавлена новая категория предупреждений ResourceWarning. Он генерируется при обнаружении потенциальных проблем с потреблением ресурсов или очисткой. По умолчанию в сборках обычных релизов он отключён, но его можно включить с помощью модуля warnings или в командной строке.

    ResourceWarning выдается при завершении работы интерпретатора, если список gc.garbage не пуст, и если установлен gc.DEBUG_UNCOLLECTABLE, печатаются все объекты, которые невозможно собрать. Это предназначено для того, чтобы программист знал, что его код содержит проблемы с завершением объекта.

    ResourceWarning также выдается, когда файловый объект уничтожается без явного закрытия. Хотя средство освобождения такого объекта обеспечивает закрытие базового ресурса операционной системы (обычно файлового дескриптора), задержка освобождения объекта может привести к различным проблемам, особенно в Windows. Вот пример включения предупреждения из командной строки:

    $ python -q -Wdefault
    >>> f = open("foo", "wb")
    >>> del f
    __main__:1: ResourceWarning: unclosed file <_io.BufferedWriter name='foo'>
    

    (Добавлено Антуаном Питру и Георгом Брандлом в bpo-10093 и bpo-477863.)

  • Объекты range теперь поддерживают методы index и count. Это часть усилий по созданию большего количества объектов, полностью реализующих collections.Sequence абстрактный базовый класс. В результате язык будет иметь более унифицированный API. Кроме того, объекты range теперь поддерживают срезы и отрицательные индексы даже со значениями, превышающими sys.maxsize. Это делает range более совместимым со списками:

    >>> range(0, 100, 2).count(10)
    1
    >>> range(0, 100, 2).index(10)
    5
    >>> range(0, 100, 2)[5]
    10
    >>> range(0, 100, 2)[0:5]
    range(0, 10, 2)
    

    (Предоставлено Даниэлем Штуцбахом в bpo-9213, Александром Белопольским в bpo-2690 и Ником Когланом в bpo-10889.)

  • Возрождена встроенная функция callable() из Py2.x. Это краткая и удобочитаемая альтернатива использованию абстрактных базовых классов в таком выражении, как isinstance(x, collections.Callable):

    >>> callable(max)
    True
    >>> callable(20)
    False
    

    (См. bpo-10518.)

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

(Требуется обширная работа Виктора Стиннера в bpo-9425.)

Новые, улучшенные и устаревшие модули

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

Самая большая новость для Python 3.2 заключается в том, что пакет email, модуль mailbox и модули nntplib теперь корректно работают с моделью байт/текст в Python 3. Впервые реализована правильная обработка сообщений со смешанными кодировками.

Во всей стандартной библиотеке более пристальное внимание уделялось кодировкам и проблемам с текстом и байтами. В частности, взаимодействие с операционной системой теперь позволяет лучше обмениваться данными, отличными от ASCII, с использованием кодировки Windows MBCS, кодировки с учётом локали или UTF-8.

Ещё одним важным достижением является добавление значительно улучшенной поддержки соединений SSL и сертификатов безопасности.

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

email

Удобство использования пакета email в Python 3 было в основном исправлено благодаря обширным усилиям Р. Дэвида Мюррея. Проблема заключалась в том, что электронные письма обычно читаются и хранятся в виде текста bytes, а не str, и они могут содержать несколько кодировок в одном электронном письме. Таким образом, пакет email должен был быть расширен для анализа и создания сообщений электронной почты в байтовом формате.

  • Новые функции message_from_bytes() и message_from_binary_file(), а также новые классы BytesFeedParser и BytesParser позволяют преобразовывать двоичные данные сообщений в объекты модели.

  • При вводе байтов в модель get_payload() по умолчанию декодирует тело сообщения, которое имеет Content- Transfer-Encoding 8bit, используя кодировку, указанную в заголовках MIME, и возвращает результирующую строку.

  • Учитывая ввод байтов в модель, Generator преобразует тела сообщений, которые имеют Content-Transfer- Encoding из 8bit, в 7bit Content-Transfer-Encoding.

    Заголовки с незакодированными байтами, отличными от ASCII, считаются кодированными RFC 2047 с использованием набора символов unknown-8bit.

  • Новый класс BytesGenerator создаёт байты в качестве вывода, сохраняя любые неизмененные данные, отличные от ASCII, которые присутствовали во входных данных, используемых для построения модели, включая тела сообщений с Content-Transfer-Encoding из 8bit.

  • Класс smtplib SMTP теперь принимает строку байтов для аргумента msg метода sendmail(), а новый метод send_message() принимает объект Message и может дополнительно получать адреса from_addr и to_addrs непосредственно из объекта.

(Предложено и реализовано Р. Дэвидом Мюрреем, bpo-4661 и bpo-10321.)

elementtree

Пакет xml.etree.ElementTree и его аналог xml.etree.cElementTree обновлены до версии 1.3.

Добавлено несколько новых и полезных функций и методов:

Два метода устарели:

  • Вместо xml.etree.ElementTree.getchildren() используйте list(elem).
  • Вместо xml.etree.ElementTree.getiterator() используйте Element.iter.

Дополнительные сведения об обновлении см. в статье Знакомство с ElementTree на веб-сайте Фредрика Лунда.

(Предоставили Флоран Шиклуна и Фредрик Лунд, bpo-6472.)

functools

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

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

    >>> import functools
    >>> @functools.lru_cache(maxsize=300)
    ... def get_phone_number(name):
    ...     c = conn.cursor()
    ...     c.execute('SELECT phonenumber FROM phonelist WHERE name=?', (name,))
    ...     return c.fetchone()[0]
    
    >>> for name in user_requests:        # doctest: +SKIP
    ...     get_phone_number(name)        # кэшированный поиск
    

    Чтобы помочь в выборе эффективного размера кэша, обернутая функция приспособлена для отслеживания статистики кэша:

    >>> get_phone_number.cache_info()     # doctest: +SKIP
    CacheInfo(hits=4805, misses=980, maxsize=300, currsize=300)
    

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

    >>> get_phone_number.cache_clear()
    

    (Предоставлено Рэймондом Хеттингером и включает дизайнерские идеи Джима Бейкера, Мики Тебеки и Ника Коглана; см. рецепт 498245, рецепт 577479, bpo-10586 и bpo-10593.)

  • Декоратор functools.wraps() теперь добавляет атрибут __wrapped__, указывающий на исходную вызываемую функцию. Это позволяет осуществлять самоанализ обернутых функций. Он также копирует __annotations__, если он определён. И теперь он также изящно пропускает отсутствующие атрибуты, такие как __doc__, которые могут быть не определены для обернутого вызываемого объекта.

    В приведённом выше примере кеш можно удалить, восстановив исходную функцию:

    >>> get_phone_number = get_phone_number.__wrapped__    # некэшированная функция
    

    (Ник Коглан и Терренс Коул; bpo-9567, bpo-3445 и bpo-8814.)

  • Чтобы упростить написание классов с расширенными методами сравнения, новый декоратор functools.total_ordering() будет использовать существующие методы равенства и неравенства для заполнения оставшихся методов.

    Например, ввод __eq__ и __lt__ позволит total_ordering() заполнить __le__, __gt__ и __ge__:

    @total_ordering
    class Student:
        def __eq__(self, other):
            return ((self.lastname.lower(), self.firstname.lower()) ==
                    (other.lastname.lower(), other.firstname.lower()))
    
        def __lt__(self, other):
            return ((self.lastname.lower(), self.firstname.lower()) <
                    (other.lastname.lower(), other.firstname.lower()))
    

    С помощью декоратора total_ordering остальные методы сравнения заполняются автоматически.

    (Предоставлено Рэймондом Хеттингером.)

  • Чтобы помочь в переносе программ из Python 2, функция functools.cmp_to_key() преобразует функцию сравнения старого стиля в современную ключевую функцию:

    >>> # locale-aware sort order
    >>> sorted(iterable, key=cmp_to_key(locale.strcoll)) # doctest: +SKIP
    

    Примеры сортировки и краткое руководство по сортировке см. в руководстве HowTo по сортировке.

    (Предоставлено Рэймондом Хеттингером.)

itertools

  • Модуль itertools имеет новую функцию accumulate(), смоделированную на основе оператора APL scan и функции Numpy accumulate:

    >>> from itertools import accumulate
    >>> list(accumulate([8, 2, 50]))
    [8, 10, 60]
    
    >>> prob_dist = [0.1, 0.4, 0.2, 0.3]
    >>> list(accumulate(prob_dist))      # кумулятивное распределение вероятностей
    [0.1, 0.5, 0.7, 1.0]
    

    Пример использования accumulate() см. в примерах для модуля random.

    (Предоставлено Рэймондом Хеттингером и включает предложения по дизайну от Марка Дикинсона.)

collections

  • Класс collections.Counter теперь имеет две формы вычитания на месте: существующий оператор -= для насыщающего вычитания и новый метод subtract() для обычного вычитания. Первый подходит для мультимножеств, которые имеют только положительные значения, а второй больше подходит для случаев использования, допускающих отрицательные значения:

    >>> from collections import Counter
    >>> tally = Counter(dogs=5, cats=3)
    >>> tally -= Counter(dogs=2, cats=8)    # насыщающее вычитание
    >>> tally
    Counter({'dogs': 3})
    
    >>> tally = Counter(dogs=5, cats=3)
    >>> tally.subtract(dogs=2, cats=8)      # регулярное вычитание
    >>> tally
    Counter({'dogs': 3, 'cats': -5})
    

    (Предоставлено Рэймондом Хеттингером.)

  • Класс collections.OrderedDict имеет новый метод move_to_end(), который берет существующий ключ и перемещает его либо в первую, либо в последнюю позицию в упорядоченной последовательности.

    По умолчанию элемент перемещается на последнюю позицию. Это эквивалентно обновлению записи с od[k] = od.pop(k).

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

    >>> from collections import OrderedDict
    >>> d = OrderedDict.fromkeys(['a', 'b', 'X', 'd', 'e'])
    >>> list(d)
    ['a', 'b', 'X', 'd', 'e']
    >>> d.move_to_end('X')
    >>> list(d)
    ['a', 'b', 'd', 'e', 'X']
    

    (Предоставлено Рэймондом Хеттингером.)

  • Класс collections.deque пополнился двумя новыми методами count() и reverse(), которые делают их более заменяемыми для объектов list:

    >>> from collections import deque
    >>> d = deque('simsalabim')
    >>> d.count('s')
    2
    >>> d.reverse()
    >>> d
    deque(['m', 'i', 'b', 'a', 'l', 'a', 's', 'm', 'i', 's'])
    

    (Предоставлено Рэймондом Хеттингером.)

threading

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

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

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

Пример использования барьеров:

from threading import Barrier, Thread

def get_votes(site):
    ballots = conduct_election(site)
    all_polls_closed.wait()        # не подсчитывать, пока все пулы не будут закрыты
    totals = summarize(ballots)
    publish(site, totals)

all_polls_closed = Barrier(len(sites))
for site in sites:
    Thread(target=get_votes, args=(site,)).start()

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

Если какая-либо из предшествующих задач может зависнуть или задерживаться, можно создать барьер с помощью дополнительного параметра timeout. Затем, если период ожидания истекает до того, как все предшествующие задачи достигнут точки барьера, все ожидающие потоки освобождаются и возникает исключение BrokenBarrierError:

def get_votes(site):
    ballots = conduct_election(site)
    try:
        all_polls_closed.wait(timeout=midnight - time.now())
    except BrokenBarrierError:
        lockbox = seal_ballots(ballots)
        queue.put(lockbox)
    else:
        totals = summarize(ballots)
        publish(site, totals)

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

Дополнительные примеры использования барьеров в параллельных вычислениях см. в Шаблоны синхронизации барьеров. Также есть простое, но подробное объяснение барьеров в Маленькая книга семафоров, раздел 3.6.

(Предоставлено Кристьяном Валуром Йонссоном с обзором API Джеффри Яскина в bpo-8777.)

datetime и time

  • У модуля datetime появился новый тип timezone, который реализует интерфейс tzinfo, возвращая фиксированное смещение UTC и имя часового пояса. Это упрощает создание объектов даты и времени с учётом часового пояса:

    >>> from datetime import datetime, timezone
    
    >>> datetime.now(timezone.utc)
    datetime.datetime(2010, 12, 8, 21, 4, 2, 923754, tzinfo=datetime.timezone.utc)
    
    >>> datetime.strptime("01/01/2000 12:00 +0000", "%m/%d/%Y %H:%M %z")
    datetime.datetime(2000, 1, 1, 12, 0, tzinfo=datetime.timezone.utc)
    
  • Кроме того, объекты timedelta теперь можно умножать на float и делить на объекты float и int. А объекты timedelta теперь могут делить друг друга.

  • Метод datetime.date.strftime() больше не ограничен годами после 1900. Новый поддерживаемый диапазон лет — от 1000 до 9999 включительно.

  • Всякий раз, когда в кортеже времени используется двузначный год, интерпретация регулируется time.accept2dyear. Значение по умолчанию — True, что означает, что для года, состоящего из двух цифр, век угадывается в соответствии с правилами POSIX, управляющими форматом %y strptime.

    Начиная с Py3.2, использование эвристики угадывания века будет выдавать DeprecationWarning. Вместо этого рекомендуется установить для time.accept2dyear значение False, чтобы можно было без догадок использовать большие диапазоны дат:

    >>> import time, warnings
    >>> warnings.resetwarnings()      # удалить фильтры предупреждений по умолчанию
    
    >>> time.accept2dyear = True      # угадать, означает ли 11 11 или 2011
    >>> time.asctime((11, 1, 1, 12, 34, 56, 4, 1, 0))
    Warning (from warnings module):
      ...
    DeprecationWarning: Century info guessed for a 2-digit year.
    'Fri Jan  1 12:34:56 2011'
    
    >>> time.accept2dyear = False     # использовать весь диапазон допустимых дат
    >>> time.asctime((11, 1, 1, 12, 34, 56, 4, 1, 0))
    'Fri Jan  1 12:34:56 11'
    

    Несколько функций теперь имеют значительно расширенные диапазоны дат. Когда time.accept2dyear имеет значение ложь, функция time.asctime() примет любой год, который помещается в C int, а функции time.mktime() и time.strftime() примут полный диапазон, поддерживаемый соответствующими функциями операционной системы.

(Предоставлено Александром Белопольским и Виктором Стиннером в bpo-1289118, bpo-5094, bpo-6641, bpo-2706, bpo-1777412, bpo-8013 и bpo-10827.)

math

Модуль math был обновлен шестью новыми функциями, вдохновленными стандартом C99.

Функция isfinite() обеспечивает надежный и быстрый способ обнаружения специальных значений. Он возвращает True для обычных номеров и False для Nan или Infinity:

>>> from math import isfinite
>>> [isfinite(x) for x in (123, 4.56, float('Nan'), float('Inf'))]
[True, True, False, False]

Функция expm1() вычисляет e**x-1 для небольших значений x без потери точности, которая обычно сопровождает вычитание почти равных величин:

>>> from math import expm1
>>> expm1(0.013671875)   # more accurate way to compute e**x-1 for a small x
0.013765762467652909

Функция erf() вычисляет интеграл вероятности или Функция ошибки Гаусса. Дополнительная функция ошибок erfc() имеет вид 1 - erf(x):

>>> from math import erf, erfc, sqrt
>>> erf(1.0/sqrt(2.0))   # часть нормального распределения в пределах 1 стандартного отклонения
0.682689492137086
>>> erfc(1.0/sqrt(2.0))  # часть нормального распределения за пределами 1 стандартного отклонения
0.31731050786291404
>>> erf(1.0/sqrt(2.0)) + erfc(1.0/sqrt(2.0))
1.0

Функция gamma() является непрерывным расширением функции факториала. Подробнее см. https://en.wikipedia.org/wiki/Gamma_function. Поскольку функция связана с факториалами, она увеличивается даже при малых значениях x, поэтому существует также функция lgamma() для вычисления натурального логарифма гамма-функции:

>>> from math import gamma, lgamma
>>> gamma(7.0)           # факториал шести
720.0
>>> lgamma(801.0)        # log(800 factorial)
4551.950730698041

(Предоставлено Марком Дикинсоном.)

abc

Модуль abc теперь поддерживает abstractclassmethod() и abstractstaticmethod().

Данные инструменты позволяют определить абстрактный базовый класс, для которого требуется classmethod() или staticmethod():

class Temperature(metaclass=abc.ABCMeta):
    @abc.abstractclassmethod
    def from_fahrenheit(cls, t):
        ...
    @abc.abstractclassmethod
    def from_celsius(cls, t):
        ...

(Исправление предоставлено Дэниелом Урбаном; bpo-5867.)

io

io.BytesIO имеет новый метод getbuffer(), который предоставляет функциональные возможности, аналогичные memoryview(). Он создаёт редактируемое представление данных без создания копии. Произвольный доступ к буферу и поддержка записи срезов хорошо подходят для редактирования на месте:

>>> REC_LEN, LOC_START, LOC_LEN = 34, 7, 11

>>> def change_location(buffer, record_number, location):
...     start = record_number * REC_LEN + LOC_START
...     buffer[start: start+LOC_LEN] = location

>>> import io

>>> byte_stream = io.BytesIO(
...     b'G3805  storeroom  Main chassis    '
...     b'X7899  shipping   Reserve cog     '
...     b'L6988  receiving  Primary sprocket'
... )
>>> buffer = byte_stream.getbuffer()
>>> change_location(buffer, 1, b'warehouse  ')
>>> change_location(buffer, 0, b'showroom   ')
>>> print(byte_stream.getvalue())
b'G3805  showroom   Main chassis    '
b'X7899  warehouse  Reserve cog     '
b'L6988  receiving  Primary sprocket'

(Предоставлено Антуаном Питру в bpo-5506.)

reprlib

При написании метода __repr__() для пользовательского контейнера легко забыть обработать случай, когда элемент ссылается на сам контейнер. Встроенные объекты Python list и set, обрабатывают ссылку на самих себя, отображая «…» в рекурсивной части строки представления.

Чтобы упростить написание таких методов __repr__(), модуль reprlib имеет новый декоратор recursive_repr() для обнаружения рекурсивных вызовов __repr__() и замены строки-заполнителя:

>>> class MyList(list):
...     @recursive_repr()
...     def __repr__(self):
...         return '<' + '|'.join(map(repr, self)) + '>'
...
>>> m = MyList('abc')
>>> m.append(m)
>>> m.append('x')
>>> print(m)
<'a'|'b'|'c'|...|'x'>

(Предоставлено Рэймондом Хеттингером в bpo-9826 и bpo-9840.)

logging

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

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

Функция настройки logging.basicConfig() получила аргумент style для поддержки трёх различных типов форматирования строк. По умолчанию используется «%» для традиционного %-форматирования, может быть установлено значение «{» для нового стиля str.format() или значение «$» для форматирования в стиле оболочки, предоставляемого string.Template. Следующие три конфигурации эквивалентны:

>>> from logging import basicConfig
>>> basicConfig(style='%', format="%(name)s -> %(levelname)s: %(message)s")
>>> basicConfig(style='{', format="{name} -> {levelname} {message}")
>>> basicConfig(style='$', format="$name -> $levelname: $message")

Если никакая конфигурация не настроена до возникновения события логгирования, теперь существует конфигурация по умолчанию с использованием StreamHandler, направленного на sys.stderr для событий уровня WARNING или выше. Ранее событие, происходящее перед настройкой конфигурации, либо вызывало исключение, либо автоматически удаляло событие в зависимости от значения logging.raiseExceptions. Новый обработчик по умолчанию хранится в logging.lastResort.

Использование фильтров было упрощено. Вместо создания объекта Filter предикатом может быть любой вызываемый объект Python, который возвращает True или False.

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

csv

Модуль csv теперь поддерживает новый диалект, unix_dialect, который применяет кавычки для всех полей и традиционный стиль Unix с '\n' в качестве конца строки. Зарегистрированное название диалекта — unix.

csv.DictWriter имеет новый метод writeheader() для записи начальной строки для документирования имён полей:

>>> import csv, sys
>>> w = csv.DictWriter(sys.stdout, ['name', 'dept'], dialect='unix')
>>> w.writeheader()
"name","dept"
>>> w.writerows([
...     {'name': 'tom', 'dept': 'accounting'},
...     {'name': 'susan', 'dept': 'Salesl'}])
"tom","accounting"
"susan","sales"

(Новый диалект, предложенный Джеем Талботом в bpo-5975, и новый метод, предложенный Эдом Абрахамом в bpo-1537721.)

contextlib

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

Для удобства новая функциональность используется contextmanager(), поэтому для поддержки обеих ролей не требуется дополнительных усилий.

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

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

from contextlib import contextmanager
import logging

logging.basicConfig(level=logging.INFO)

@contextmanager
def track_entry_and_exit(name):
    logging.info('Entering: %s', name)
    yield
    logging.info('Exiting: %s', name)

Раньше это можно было использовать только в качестве менеджера контекста:

with track_entry_and_exit('widget loader'):
    print('Some time consuming activity goes here')
    load_widget()

Теперь его можно использовать и как декоратор:

@track_entry_and_exit('widget loader')
def activity():
    print('Some time consuming activity goes here')
    load_widget()

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

В приведённом выше примере у менеджера контекста track_entry_and_exit нет простого способа возвращения экземпляра логгера для использования в теле операторов.

(Предоставлено Майклом Фурдом в bpo-9110.)

Десятичные и дроби

Марк Дикинсон разработал элегантную и эффективную схему, гарантирующую, что различные числовые типы данных будут иметь одно и то же хэш-значение, когда их фактические значения равны (bpo-8188):

assert hash(Fraction(3, 2)) == hash(1.5) == \
       hash(Decimal("1.5")) == hash(complex(1.5, 0))

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

>>> sys.hash_info # doctest: +SKIP
sys.hash_info(width=64, modulus=2305843009213693951, inf=314159, nan=0, imag=1000003)

Раннее решение об ограничении функциональной совместимости различных числовых типов было смягчено. По-прежнему не поддерживается (и не рекомендуется) иметь неявное смешивание в арифметических выражениях, таких как Decimal('1.1') + float('1.1'), потому что последнее теряет информацию в процессе построения двоичного числа с плавающей запятой. Однако, поскольку существующие значения с плавающей запятой могут быть без потерь преобразованы либо в десятичное, либо в рациональное представление, имеет смысл добавить их в конструктор и поддерживать сравнения смешанного типа.

  • Конструктор decimal.Decimal теперь принимает объекты float напрямую, поэтому больше нет необходимости использовать метод from_float() (bpo-8257).
  • Сравнения смешанного типа теперь полностью поддерживаются, поэтому объекты Decimal можно напрямую сравнивать с float и fractions.Fraction (bpo-2531 и bpo-8188).

Аналогичные изменения были внесены в fractions.Fraction, так что методы from_float() и from_decimal() больше не нужны (bpo-8294):

>>> from decimal import Decimal
>>> from fractions import Fraction
>>> Decimal(1.1)
Decimal('1.100000000000000088817841970012523233890533447265625')
>>> Fraction(1.1)
Fraction(2476979795053773, 2251799813685248)

Ещё одно полезное изменение для модуля decimal заключается в том, что атрибут Context.clamp теперь общедоступен. Это полезно при создании контекстов, соответствующих десятичным форматам обмена, указанным в IEEE 754 (см. bpo-8540).

(Предоставлено Марком Дикинсоном и Рэймондом Хеттингером.)

ftplib

Класс ftplib.FTP теперь поддерживает протокол управления контекстом для безусловного использования исключений socket.error и закрытия FTP- соединения по завершении:

>>> from ftplib import FTP
>>> with FTP("ftp1.at.proftpd.org") as ftp:
        ftp.login()
        ftp.dir()

'230 Anonymous login ok, restrictions apply.'
dr-xr-xr-x   9 ftp      ftp           154 May  6 10:43 .
dr-xr-xr-x   9 ftp      ftp           154 May  6 10:43 ..
dr-xr-xr-x   5 ftp      ftp          4096 May  6 10:43 CentOS
dr-xr-xr-x   3 ftp      ftp            18 Jul 10  2008 Fedora

Другие файловые объекты, такие как mmap.mmap и fileinput.input(), также стали автоматически закрывающимися менеджерами контекста:

with fileinput.input(files=('log1.txt', 'log2.txt')) as f:
    for line in f:
        process(line)

(Предоставлено Тареком Зиаде и Джампаоло Родола в bpo-4972 и Георгом Брандлом в bpo-8046 и bpo-1286.)

Класс FTP_TLS теперь принимает параметр context, который представляет собой объект ssl.SSLContext, позволяющий объединять параметры конфигурации SSL, сертификаты и закрытые ключи в единую (потенциально долгоживущую) структуру.

(Предоставлено Джампаоло Родола; bpo-8806.)

popen

Функции os.popen() и subprocess.Popen() теперь поддерживают операторы with для автоматического закрытия файловых дескрипторов.

(Предоставлено Антуаном Питру и Брайаном Кертином в bpo-7461 и bpo-10554.)

select

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

>>> import select
>>> select.PIPE_BUF  # doctest: +SKIP
512

(Доступно в системах Unix. Исправление Себастьяна Сабле в bpo-9862)

gzip и zipfile

gzip.GzipFile теперь реализует io.BufferedIOBase абстрактный базовый класс (кроме truncate()). Он также имеет метод peek() и поддерживает файловые объекты без поиска, а также с нулевым наполнением.

Модуль gzip также получает функции compress() и decompress() для упрощения сжатия и распаковки в памяти. Имейте в виду, что перед сжатием и распаковкой текст должен быть закодирован как bytes:

>>> import gzip
>>> s = 'Three shall be the number thou shalt count, '
>>> s += 'and the number of the counting shall be three'
>>> b = s.encode()                        # преобразовать в utf-8
>>> len(b)
89
>>> c = gzip.compress(b)
>>> len(c)
77
>>> gzip.decompress(c).decode()[:42]      # распаковать и преобразовать в текст
'Three shall be the number thou shalt count'

(Предоставлено Анандом Б. Пиллаи в bpo-3488; и Антуаном Питру, Ниром Эйдесом и Брайаном Кертином в bpo-9962, bpo-1675951, bpo-7471 и bpo-2846.)

Кроме того, класс zipfile.ZipExtFile был внутренне переработан для представления файлов, хранящихся внутри архива. Новая реализация значительно быстрее и может быть заключена в объект io.BufferedReader для большего ускорения. Это также решает проблему, из-за которой чередующиеся вызовы read и readline давали неправильные результаты.

(Исправление представлено Nir Aides в bpo-7610.)

tarfile

Класс TarFile теперь можно использовать в качестве менеджера контекста. Кроме того, его метод add() имеет новый параметр filter, который определяет, какие файлы добавляются в архив, и позволяет редактировать метаданные файлов.

Новый параметр filter заменяет старый, менее гибкий параметр exclude, который в настоящее время устарел. Если указано, необязательный параметр filter должен быть ключевым аргументом. Предоставляемая пользователем функция фильтра принимает объект TarInfo и возвращает обновленный объект TarInfo, или, если она хочет, чтобы файл был исключен, функция может возвращать None:

>>> import tarfile, glob

>>> def myfilter(tarinfo):
...     if tarinfo.isfile():             # сохранять только реальные файлы
...         tarinfo.uname = 'monty'      # отредактировать имя пользователя
...         return tarinfo

>>> with tarfile.open(name='myarchive.tar.gz', mode='w:gz') as tf:
...     for filename in glob.glob('*.txt'):
...         tf.add(filename, filter=myfilter)
...     tf.list()
-rw-r--r-- monty/501        902 2011-01-26 17:59:11 annotations.txt
-rw-r--r-- monty/501        123 2011-01-26 17:59:11 general_questions.txt
-rw-r--r-- monty/501       3514 2011-01-26 17:59:11 prion.txt
-rw-r--r-- monty/501        124 2011-01-26 17:59:11 py_todo.txt
-rw-r--r-- monty/501       1399 2011-01-26 17:59:11 semaphore_notes.txt

(Предложено Тареком Зиади и реализовано Ларсом Густабелем в bpo-6856.)

hashlib

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

>>> import hashlib

>>> hashlib.algorithms_guaranteed
{'sha1', 'sha224', 'sha384', 'sha256', 'sha512', 'md5'}

>>> hashlib.algorithms_available
{'md2', 'SHA256', 'SHA512', 'dsaWithSHA', 'mdc2', 'SHA224', 'MD4', 'sha256',
'sha512', 'ripemd160', 'SHA1', 'MDC2', 'SHA', 'SHA384', 'MD2',
'ecdsa-with-SHA1','md4', 'md5', 'sha1', 'DSA-SHA', 'sha224',
'dsaEncryption', 'DSA', 'RIPEMD160', 'sha', 'MD5', 'sha384'}

(Предложено Карлом Шене в bpo-7418.)

ast

Модуль ast имеет замечательный инструмент общего назначения для безопасной вычисления строк выражений с использованием литерального синтаксиса Python. Функция ast.literal_eval() служит безопасной альтернативой встроенной функции eval(), которой легко злоупотреблять. Python 3.2 добавляет литералы bytes и set в список поддерживаемых типов: строки, байты, числа, кортежи, списки, словари, наборы, логические значения и None.

>>> from ast import literal_eval

>>> request = "{'req': 3, 'func': 'pow', 'args': (2, 0.5)}"
>>> literal_eval(request)
{'args': (2, 0.5), 'req': 3, 'func': 'pow'}

>>> request = "os.system('do something harmful')"
>>> literal_eval(request)
Traceback (most recent call last):
  ...
ValueError: malformed node or string: <_ast.Call object at 0x101739a10>

(Реализовано Бенджамином Петерсоном и Георгом Брандлом.)

os

Различные операционные системы используют различные кодировки для имён файлов и переменных среды. Модуль os предоставляет две новые функции, fsencode() и fsdecode(), для кодирования и декодирования имён файлов:

>>> import os
>>> filename = 'Sehenswürdigkeiten'
>>> os.fsencode(filename)
b'Sehensw\xc3\xbcrdigkeiten'

Некоторые операционные системы разрешают прямой доступ к закодированным байтам в среде. Если да, то константа os.supports_bytes_environ будет истинной.

Для прямого доступа к закодированным переменным среды (если они доступны) используйте новую функцию os.getenvb() или os.environb, которая является байтовой версией os.environ.

(Предоставлено Виктором Стиннером.)

shutil

У функции shutil.copytree() появилось два новых параметра:

  • ignore_dangling_symlinks: когда symlinks=False, чтобы функция копировала файл, на который указывает символическая ссылка, а не саму символическую ссылку. Опция заглушит возникшую ошибку, если файл не существует.
  • copy_function: вызываемый объект, который будет использоваться для копирования файлов. shutil.copy2() используется по умолчанию.

(Предоставлено Тареком Зиаде.)

Кроме того, модуль shutil теперь поддерживает архивные операции для zip-файлов, несжатых tar-файлов, tar-файлов, сжатых gzip, и tar-файлов, сжатых bzip. И есть функции для регистрации дополнительных форматов архивных файлов (например, сжатые tar-файлы xz или пользовательские форматы).

Основные функции: make_archive() и unpack_archive(). По умолчанию оба работают с текущим каталогом (который можно установить с помощью os.chdir()) и с любыми подкаталогами. Имя файла архива должно быть указано с полным путём. Этап архивирования является неразрушающим (исходные файлы остаются без изменений).

>>> import shutil, pprint

>>> os.chdir('mydata')  # перейти в исходный каталог
>>> f = shutil.make_archive('/var/backup/mydata',
...                         'zip')      # заархивировать текущий каталог
>>> f                                   # показать имя архива
'/var/backup/mydata.zip'
>>> os.chdir('tmp')                     # change to an unpacking
>>> shutil.unpack_archive('/var/backup/mydata.zip')  # перейти на распаковку

>>> pprint.pprint(shutil.get_archive_formats())  # восстановить данные
[('bztar', "bzip2'ed tar-file"),
 ('gztar', "gzip'ed tar-file"),
 ('tar', 'uncompressed tar file'),
 ('zip', 'ZIP file')]

>>> shutil.register_archive_format(     # зарегистрировать новый формат архива
...     name='xz',
...     function=xz.compress,           # вызываемая функция архивации
...     extra_args=[('level', 8)],      # аргументы функции
...     description='xz compression'
... )

(Предоставлено Тареком Зиаде.)

sqlite3

Модуль sqlite3 обновлен до версии pysqlite 2.6.0. У него есть две новые возможности.

  • Атрибут sqlite3.Connection.in_transit имеет значение истина, если есть активная транзакция для незафиксированных изменений.
  • Методы sqlite3.Connection.enable_load_extension() и sqlite3.Connection.load_extension() позволяют загружать расширения SQLite из файлов «.so». Одним из широко известных расширений является расширение полнотекстового поиска, распространяемое вместе с SQLite.

(Предоставлено Р. Дэвидом Мюрреем и Шашватом Анандом; bpo-8845.)

html

Был введен новый модуль html с единственной функцией, escape(), которая используется для экранирования зарезервированных символов из разметки HTML:

>>> import html
>>> html.escape('x > 2 && x < 7')
'x &gt; 2 &amp;&amp; x &lt; 7'

socket

Модуль socket имеет два новых улучшения.

  • Объекты сокетов теперь имеют метод detach(), который переводит сокет в закрытое состояние без фактического закрытия базового файлового дескриптора. Последнюю можно повторно использовать для других целей. (Добавлено Антуаном Питру; bpo-8524.)
  • socket.create_connection() теперь поддерживает протокол управления контекстом для безусловного использования исключений socket.error и закрытия сокета по завершении. (Предоставлено Джампаоло Родола; bpo-9794.)

ssl

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

  • Новый класс SSLContext служит контейнером для постоянных данных SSL: настройки протокола, сертификаты, закрытые ключи и различные другие параметры. Он включает wrap_socket() для создания SSL сокета из SSL контекста.
  • Новая функция ssl.match_hostname() поддерживает проверку подлинности сервера для протоколов более высокого уровня путём реализации правил HTTPS (из RFC 2818), которые также подходят для других протоколов.
  • Функция-конструктор ssl.wrap_socket() теперь принимает аргумент ciphers. В строке ciphers перечислены разрешенные алгоритмы шифрования в формате, описанном в документации по OpenSSL.
  • При подключении к последним версиям OpenSSL модуль ssl теперь поддерживает расширение Server Name Indication для протокола TLS, позволяя нескольким «виртуальным хостам» использовать разные сертификаты на одном IP- порту. Это расширение поддерживается только в клиентском режиме и активируется передачей аргумента server_hostname в ssl.SSLContext.wrap_socket().
  • В модуль ssl были добавлены различные параметры, такие как OP_NO_SSLv2, который отключает небезопасный и устаревший протокол SSLv2.
  • Теперь расширение загружает все шифры и алгоритмы дайджеста OpenSSL. Если некоторые SSL-сертификаты не могут быть проверены, о них сообщается как об ошибке «неизвестный алгоритм».
  • Используемая версия OpenSSL теперь доступна с помощью атрибутов модуля ssl.OPENSSL_VERSION (строка), ssl.OPENSSL_VERSION_INFO (кортеж из 5) и ssl.OPENSSL_VERSION_NUMBER (целое число).

(Предоставлено Антуаном Питру в bpo-8850, bpo-1589, bpo-8322, bpo-5639, bpo-4870, bpo-8484 и bpo-8321.)

nntplib

У модуля nntplib обновилась реализация с улучшенной байтовой и текстовой семантикой, а также более практичными API. Данные улучшения нарушают совместимость с версией nntplib в Python 3.1, которая сама по себе частично нефункциональна.

Также была добавлена поддержка безопасных подключений через неявный (с использованием nntplib.NNTP_SSL) и явный (с использованием nntplib.NNTP.starttls()) TLS.

(Предоставлено Антуаном Питру в bpo-9360 и Эндрю Вантом в bpo-1926.)

Сертификаты

http.client.HTTPSConnection, urllib.request.HTTPSHandler и urllib.request.urlopen() теперь принимают необязательные аргументы, чтобы разрешить проверку сертификата сервера по набору центров сертификации, как это рекомендуется при общедоступном использовании HTTPS.

(Добавлено Антуаном Питру, bpo-9003.)

imaplib

Поддержка явного TLS для стандартных подключений IMAP4 была добавлена с помощью нового метода imaplib.IMAP4.starttls.

(Предоставлено Лоренцо М. Катуччи и Антуаном Питру, bpo-4471.)

http.client

В модуле http.client был внесён ряд небольших улучшений API. Простые ответы HTTP 0.9 в старом стиле больше не поддерживаются, а параметр strict устарел во всех классах.

Классы HTTPConnection и HTTPSConnection теперь имеют параметр source_address для кортежа (хост, порт), указывающего, откуда установлено HTTP-соединение.

В HTTPSConnection добавлена поддержка проверки сертификатов и виртуальных хостов HTTPS.

Метод request() для объектов подключения допускал необязательный аргумент body, чтобы можно было использовать файловый объект для предоставления содержимого запроса. Удобно, что аргумент body теперь также принимает объект итерируемый, если он включает явный заголовок Content-Length. Данный расширенный интерфейс гораздо более гибкий, чем раньше.

Для установки соединения HTTPS через прокси-сервер существует новый метод set_tunnel(), который устанавливает хост и порт для туннелирования HTTP Connect.

Чтобы соответствовать поведению http.server, клиентская библиотека HTTP теперь также кодирует заголовки в кодировке ISO-8859-1 (Latin-1). Он уже делал это для входящих заголовков, так что теперь поведение одинаково как для входящего, так и для исходящего трафика. (См. работу Армина Ронахера в bpo-10980.)

unittest

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

  • Вызов командной строки python -m unittest теперь может принимать пути к файлам вместо имён модулей для запуска определенных тестов (bpo-10620). Новое обнаружение тестов может находить тесты в пакетах, обнаруживая любой тест, который можно импортировать из каталога верхнего уровня. Каталог верхнего уровня можно указать с помощью параметра -t, шаблон для сопоставления файлов с -p и каталог для начала обнаружения с -s:

    $ python -m unittest discover -s my_proj_dir -p _test.py
    

    (Предоставлено Майклом Фордом.)

  • Экспериментировать в интерактивном приглашении стало проще, потому что класс unittest.case.TestCase теперь можно создавать без аргументов:

    >>> from unittest import TestCase
    >>> TestCase().assertEqual(pow(2, 3), 8)
    

    (Предоставлено Майклом Фордом.)

  • Модуль unittest имеет два новых метода, assertWarns() и assertWarnsRegex(), для проверки того, что данный тип предупреждения инициируется тестируемым кодом:

    with self.assertWarns(DeprecationWarning):
        legacy_function('XYZ')
    

    (Предоставлено Антуаном Питру, bpo-9754.)

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

    def test_anagram(self):
        self.assertCountEqual('algorithm', 'logarithm')
    

    (Предоставлено Рэймондом Хеттингером.)

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

  • Кроме того, имена методов в модуле подверглись ряду исправлений.

    Например, assertRegex() — это новое имя для assertRegexpMatches(), которое было названо неправильно, поскольку в тесте используется re.search(), а не re.match(). Другие методы, использующие регулярные выражения, теперь именуются с использованием краткой формы «Regex» вместо «Regexp» — это соответствует именам, используемым в других реализациях unittest, соответствует старому имени Python для модуля re и имеет недвусмысленный верблюжью нотацию.

    (Предоставлено Рэймондом Хеттингером и реализовано Эцио Мелотти.)

  • Чтобы улучшить согласованность, некоторые устаревшие псевдонимы методов устарели в пользу предпочтительных имён:

    Старое имя Предпочтительное имя
    assert_() assertTrue()
    assertEquals() assertEqual()
    assertNotEquals() assertNotEqual()
    assertAlmostEquals() assertAlmostEqual()
    assertNotAlmostEquals() assertNotAlmostEqual()

    Аналогичным образом ожидается, что методы TestCase.fail*, объявленные устаревшими в Python 3.1, будут удалены в Python 3.3. Также см. раздел Устаревшие псевдонимы в документации unittest.

    (Предоставлено Эцио Мелотти; bpo-9424.)

  • Метод assertDictContainsSubset() устарел, поскольку он был неправильно реализован с аргументами в неправильном порядке. Это создавало трудно поддающиеся отладке оптические иллюзии, когда такие тесты, как TestCase().assertDictContainsSubset({'a':1, 'b':2}, {'a':1}), не удавались.

    (Предоставлено Рэймондом Хеттингером.)

random

Целочисленные методы в модуле random теперь лучше справляются с созданием однородных распределений. Ранее они вычисляли выборки с int(n*random()), которые имели небольшое смещение всякий раз, когда n не было степенью двойки. Теперь выполняется множественный выбор из диапазона до следующей степени двойки, и выбор сохраняется только в том случае, если он попадает в диапазон 0 <= x < n. Затронутые функции и методы: randrange(), randint(), choice(), shuffle() и sample().

(Предоставлено Рэймондом Хеттингером; bpo-9025.)

poplib

Класс POP3_SSL теперь принимает параметр context, который представляет собой объект ssl.SSLContext, позволяющий объединять параметры конфигурации SSL, сертификаты и закрытые ключи в единую (потенциально долгоживущую) структуру.

(Предоставлено Джампаоло Родола; bpo-8807.)

asyncore

asyncore.dispatcher теперь предоставляет метод handle_accepted(), возвращающий пару (sock, addr), которая вызывается, когда соединение действительно установлено с новой удаленной конечной точкой. Предполагается, что он используется в качестве замены старого handle_accept() и позволяет пользователю не вызывать accept() напрямую.

(Предоставлено Джампаоло Родола; bpo-6706.)

tempfile

У модуля tempfile появился новый менеджер контекста, TemporaryDirectory, который обеспечивает простую детерминированную очистку временных каталогов:

with tempfile.TemporaryDirectory() as tmpdirname:
    print('created temporary dir:', tmpdirname)

(Предоставлено Нилом Шеменауэром и Ником Когланом; bpo-5178.)

inspect

  • Модуль inspect имеет новую функцию getgeneratorstate(), позволяющую легко определить текущее состояние генератора-итератора:

    >>> from inspect import getgeneratorstate
    >>> def gen():
    ...     yield 'demo'
    >>> g = gen()
    >>> getgeneratorstate(g)
    'GEN_CREATED'
    >>> next(g)
    'demo'
    >>> getgeneratorstate(g)
    'GEN_SUSPENDED'
    >>> next(g, None)
    >>> getgeneratorstate(g)
    'GEN_CLOSED'
    

    (Предоставлено Родольфо Экхардтом и Ником Когланом, bpo-10220.)

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

    >>> class A:
    ...     @property
    ...     def f(self):
    ...         print('Running')
    ...         return 10
    ...
    >>> a = A()
    >>> getattr(a, 'f')
    Running
    10
    >>> inspect.getattr_static(a, 'f')
    <property object at 0x1022bd788>
    

(Предоставлено Майклом Фордом.)

pydoc

Модуль pydoc теперь предоставляет значительно улучшенный интерфейс веб-сервера, а также новый параметр командной строки -b для автоматического открытия окна браузера для отображения этого сервера:

$ pydoc3.2 -b

(Предоставлено Роном Адамом; bpo-2001.)

dis

Модуль dis получил две новые функции для проверки кода: code_info() и show_code(). Оба предоставляют подробную информацию об объекте кода для предоставленной функции, метода, строки исходного кода или объекта кода. Первый возвращает строку, а второй печатает её:

>>> import dis, random
>>> dis.show_code(random.choice)
Name:              choice
Filename:          /Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/random.py
Argument count:    2
Kw-only arguments: 0
Number of locals:  3
Stack size:        11
Flags:             OPTIMIZED, NEWLOCALS, NOFREE
Constants:
   0: 'Choose a random element from a non-empty sequence.'
   1: 'Cannot choose from an empty sequence'
Names:
   0: _randbelow
   1: len
   2: ValueError
   3: IndexError
Variable names:
   0: self
   1: seq
   2: i

Кроме того, функция dis() теперь принимает строковые аргументы, так что распространённая идиома dis(compile(s, '', 'eval')) может быть сокращена до dis(s):

>>> dis('3*x+1 if x%2==1 else x//2')
  1           0 LOAD_NAME                0 (x)
              3 LOAD_CONST               0 (2)
              6 BINARY_MODULO
              7 LOAD_CONST               1 (1)
             10 COMPARE_OP               2 (==)
             13 POP_JUMP_IF_FALSE       28
             16 LOAD_CONST               2 (3)
             19 LOAD_NAME                0 (x)
             22 BINARY_MULTIPLY
             23 LOAD_CONST               1 (1)
             26 BINARY_ADD
             27 RETURN_VALUE
        >>   28 LOAD_NAME                0 (x)
             31 LOAD_CONST               0 (2)
             34 BINARY_FLOOR_DIVIDE
             35 RETURN_VALUE

В совокупности данные улучшения упрощают изучение реализации CPython и позволяют увидеть, что синтаксис языка делает «внутри».

(Предоставлено Ником Когланом в bpo-9147.)

dbm

Все модули базы данных теперь поддерживают методы get() и setdefault().

(Предложено Рэем Алленом в bpo-9523.)

ctypes

Новый тип ctypes.c_ssize_t представляет тип данных C ssize_t.

site

Модуль site имеет три новые функции, полезные для создания отчётов о деталях установки Python.

  • getsitepackages() перечисляет все глобальные каталоги site- packages.
  • getuserbase() сообщает о базовом каталоге пользователя, в котором могут храниться данные.
  • getusersitepackages() показывает пользовательский путь к каталогу site-packages.
>>> import site
>>> site.getsitepackages()
['/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/site-packages',
 '/Library/Frameworks/Python.framework/Versions/3.2/lib/site-python',
 '/Library/Python/3.2/site-packages']
>>> site.getuserbase()
'/Users/raymondhettinger/Library/Python/3.2'
>>> site.getusersitepackages()
'/Users/raymondhettinger/Library/Python/3.2/lib/python/site-packages'

Удобно, что некоторые функции сайта доступны непосредственно из командной строки:

$ python -m site --user-base
/Users/raymondhettinger/.local
$ python -m site --user-site
/Users/raymondhettinger/.local/lib/python3.2/site-packages

(Предоставлено Тареком Зиаде в bpo-6693.)

sysconfig

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

Модуль предлагает простой доступ к функциям доступа к информации о платформе и версии:

  • get_platform() возвращает такие значения, как linux-i586 или macosx-10.6-ppc.
  • get_python_version() возвращает строку версии Python, например «3.2».

Он также обеспечивает доступ к путям и переменным, соответствующим одной из семи именованных схем, используемых distutils. К ним относятся posix_prefix, posix_home, posix_user, nt, nt_user, os2, os2_home:

  • get_paths() создаёт словарь, содержащий пути установки для текущей схемы установки.
  • get_config_vars() возвращает словарь переменных, специфичных для платформы.

Также имеется удобный интерфейс командной строки:

C:\Python32>python -m sysconfig
Platform: "win32"
Python version: "3.2"
Current installation scheme: "nt"

Paths:
        data = "C:\Python32"
        include = "C:\Python32\Include"
        platinclude = "C:\Python32\Include"
        platlib = "C:\Python32\Lib\site-packages"
        platstdlib = "C:\Python32\Lib"
        purelib = "C:\Python32\Lib\site-packages"
        scripts = "C:\Python32\Scripts"
        stdlib = "C:\Python32\Lib"

Variables:
        BINDIR = "C:\Python32"
        BINLIBDEST = "C:\Python32\Lib"
        EXE = ".exe"
        INCLUDEPY = "C:\Python32\Include"
        LIBDEST = "C:\Python32\Lib"
        SO = ".pyd"
        VERSION = "32"
        abiflags = ""
        base = "C:\Python32"
        exec_prefix = "C:\Python32"
        platbase = "C:\Python32"
        prefix = "C:\Python32"
        projectbase = "C:\Python32"
        py_version = "3.2"
        py_version_nodot = "32"
        py_version_short = "3.2"
        srcdir = "C:\Python32"
        userbase = "C:\Documents and Settings\Raymond\Application Data\Python"

(Перенесено из Distutils Тареком Зиаде.)

pdb

Модуль отладчика pdb получил ряд улучшений удобства использования:

  • pdb.py теперь имеет параметр -c, который выполняет команды, указанные в файле сценария .pdbrc.
  • Файл сценария .pdbrc может содержать команды continue и next, которые продолжают отладку.
  • Конструктор класса Pdb теперь принимает аргумент nosigint.
  • Новые команды: l(list), ll(long list) и source для просмотра исходного кода.
  • Новые команды: display и undisplay для отображения или скрытия значения выражения, если оно изменилось.
  • Новая команда: interact для запуска интерактивного интерпретатора, содержащего глобальные и локальные имена, найденные в текущей области.
  • Точки останова можно очистить по номеру точки останова.

(Предоставили Георг Брандл, Антонио Куни и Илья Сандлер.)

configparser

Модуль configparser был изменён для повышения удобства использования и предсказуемости анализатора по умолчанию и поддерживаемого им INI синтаксиса. Старый класс ConfigParser был удален в пользу SafeConfigParser, который, в свою очередь, был переименован в ConfigParser. Поддержка встроенных комментариев теперь отключена по умолчанию, а дубликаты разделов или параметров не допускаются в одном источнике конфигурации.

Парсеры конфигурации получили новый API, основанный на протоколе сопоставления:

>>> parser = ConfigParser()
>>> parser.read_string("""
... [DEFAULT]
... location = upper left
... visible = yes
... editable = no
... color = blue
...
... [main]
... title = Main Menu
... color = green
...
... [options]
... title = Options
... """)
>>> parser['main']['color']
'green'
>>> parser['main']['editable']
'no'
>>> section = parser['options']
>>> section['title']
'Options'
>>> section['title'] = 'Options (editable: %(editable)s)'
>>> section['title']
'Options (editable: no)'

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

Структура файла INI, принимаемая парсерами конфигурации, теперь может быть настроена. Пользователи могут указать альтернативные разделители опций/значений и префиксы комментариев, изменить имя раздела DEFAULT или переключить синтаксис интерполяции.

Существует поддержка подключаемой интерполяции, включая дополнительный обработчик интерполяции ExtendedInterpolation:

>>> parser = ConfigParser(interpolation=ExtendedInterpolation())
>>> parser.read_dict({'buildout': {'directory': '/home/ambv/zope9'},
...                   'custom': {'prefix': '/usr/local'}})
>>> parser.read_string("""
... [buildout]
... parts =
...   zope9
...   instance
... find-links =
...   ${buildout:directory}/downloads/dist
...
... [zope9]
... recipe = plone.recipe.zope9install
... location = /opt/zope
...
... [instance]
... recipe = plone.recipe.zope9instance
... zope9-location = ${zope9:location}
... zope-conf = ${custom:prefix}/etc/zope.conf
... """)
>>> parser['buildout']['find-links']
'\n/home/ambv/zope9/downloads/dist'
>>> parser['instance']['zope-conf']
'/usr/local/etc/zope.conf'
>>> instance = parser['instance']
>>> instance['zope-conf']
'/usr/local/etc/zope.conf'
>>> instance['zope9-location']
'/opt/zope'

Также были добавлены более мелкие функции поддержки указания кодировки в операциях чтения, указание резервных значений для get-функций или чтения непосредственно из словарей и строк.

(Все изменения внес Лукаш Ланга.)

urllib.parse

В модуль urllib.parse внесён ряд улучшений удобства использования.

Функция urlparse() теперь поддерживает адреса IPv6, как приведено в RFC 2732:

>>> import urllib.parse
>>> urllib.parse.urlparse('http://[dead:beef:cafe:5417:affe:8FA3:deaf:feed]/foo/') # doctest: +NORMALIZE_WHITESPACE
ParseResult(scheme='http',
            netloc='[dead:beef:cafe:5417:affe:8FA3:deaf:feed]',
            path='/foo/',
            params='',
            query='',
            fragment='')

Функция urldefrag() теперь возвращает именованный кортеж:

>>> r = urllib.parse.urldefrag('http://python.org/about/#target')
>>> r
DefragResult(url='http://python.org/about/', fragment='target')
>>> r[0]
'http://python.org/about/'
>>> r.fragment
'target'

Кроме того, функция urlencode() теперь гораздо более гибкая, принимая в качестве аргумента query либо строковый, либо байтовый тип. Если это строка, то параметры safe, encoding и error отправляются в quote_plus() для кодирования:

>>> urllib.parse.urlencode([
...      ('type', 'telenovela'),
...      ('name', '¿Dónde Está Elisa?')],
...      encoding='latin-1')
'type=telenovela&name=%BFD%F3nde+Est%E1+Elisa%3F'

Как подробно приведено в Парсинг байтов в кодировке ASCII, все функции urllib.parse теперь принимают в качестве входных данных строки байтов в кодировке ASCII, если они не смешиваются с обычными строками. Если в качестве параметров заданы строки байтов в кодировке ASCII, возвращаемые типы также будут строками байтов в кодировке ASCII:

>>> urllib.parse.urlparse(b'http://www.python.org:80/about/') # doctest: +NORMALIZE_WHITESPACE
ParseResultBytes(scheme=b'http', netloc=b'www.python.org:80',
                 path=b'/about/', params=b'', query=b'', fragment=b'')

(Работы Ника Коглана, Дэна Мана и Сентила Кумарана в bpo-2987, bpo-5468 и bpo-9873.)

mailbox

Благодаря совместным усилиям Р. Дэвида Мюррея модуль mailbox был исправлен для Python 3.2. Проблема заключалась в том, что почтовый ящик изначально был разработан с текстовым интерфейсом, но сообщения электронной почты лучше всего представляются с помощью bytes, поскольку различные части сообщения могут иметь разные кодировки.

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

Как и ожидалось, метод add() для объектов mailbox.Mailbox теперь принимает двоичный ввод.

StringIO и ввод текстового файла устарели. Кроме того, при вводе строки произойдет преждевременный сбой, если используются символы, отличные от ASCII. Раньше это приводило к сбою, когда электронная почта обрабатывалась на более позднем этапе.

Также есть поддержка бинарного вывода. Метод get_file() теперь возвращает файл в двоичном режиме (раньше он неправильно переводил файл в текстовый режим). Существует также новый метод get_bytes(), который возвращает представление сообщения bytes, соответствующее заданному key.

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

(Предоставлено Р. Дэвидом Мюрреем, усилиями Штеффена Даоде Нурпмесо и первоначальным патчем Виктора Стиннера в bpo-9124.)

turtledemo

Демонстрационный код для модуля turtle был перемещен из каталога Demo в основную библиотеку. Он включает в себя более дюжины примеров сценариев с живыми демонстрациями. Находясь на sys.path, теперь его можно запустить прямо из командной строки:

$ python -m turtledemo

(Перенесено из каталога Demo Александром Белопольским в bpo-10199.)

Многопоточность

  • Механизм сериализации выполнения одновременно работающих потоков Python (обычно известный как GIL или Глобальная блокировка интерпретатора) была переписана. Среди целей были более предсказуемые интервалы переключения и снижение накладных расходов из-за конфликта блокировок и количества последующих системных вызовов. От понятия «интервал проверки», позволяющего переключаться между потоками, отказались и заменили его абсолютной продолжительностью, выраженной в секундах. Данный параметр настраивается через sys.setswitchinterval(). В настоящее время по умолчанию установлено значение 5 миллисекунд.

    Дополнительные сведения о реализации можно прочитать в сообщение списка рассылки python-dev (однако «приоритетные запросы», представленные в этом сообщении, не были сохранены для включения).

    (Предоставлено Антуаном Питру.)

  • Обычные и рекурсивные блокировки теперь принимают необязательный аргумент timeout для своего метода acquire(). (Предоставлено Антуаном Питру; bpo-7316.)

  • Точно так же threading.Semaphore.acquire() также получил аргумент timeout. (Предоставлено Торстеном Ландшоффом; bpo-850728.)

  • Обычные и рекурсивные захваты блокировки теперь могут быть прерваны сигналами на платформах, использующих Pthreads. Это означает, что программы Python, которые блокируются при получении блокировок, могут быть успешно уничтожены повторной отправкой SIGINT процессу (нажатием Ctrl+C в большинстве оболочек). (Предоставлено Ридом Клекнером; bpo-8844.)

Оптимизации

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

  • Оптимизатор глазка (peephole) Python теперь распознает такие шаблоны, как x in {1, 2, 3}, как тест на принадлежность к набору констант. Оптимизатор преобразует set в frozenset и сохраняет предварительно построенную константу.

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

    extension = name.rpartition('.')[2]
    if extension in {'xml', 'html', 'xhtml', 'css'}:
        handle(name)
    

    (Исправление и дополнительные тесты предоставлены Дэйвом Малкольмом; bpo-6690).

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

    (Предоставлено Александром Вассалотти, Антуаном Питру и командой Unladen Swallow в bpo-9410 и bpo-3873.)

  • Timsort алгоритм, используемый в list.sort() и sorted(), теперь работает быстрее и использует меньше памяти при вызове с ключевой функции. Раньше каждый элемент списка был заключён во временный объект, который запоминал значение ключа, связанное с каждым элементом. Теперь два массива ключей и значений сортируются параллельно. Это экономит память, потребляемую оболочками сортировки, и экономит время, затрачиваемое на делегирование сравнений.

    (Исправление Даниэля Штуцбаха в bpo-9915.)

  • Производительность декодирования JSON повышается, а потребление памяти снижается всякий раз, когда одна и та же строка повторяется для нескольких ключей. Кроме того, кодирование JSON теперь использует ускорение C, когда аргумент sort_keys верен.

    (Предоставлено Антуаном Питру в bpo-7451 и Раймондом Хеттингером и Антуаном Питру в bpo-10314.)

  • Рекурсивные блокировки (созданные с помощью API threading.RLock()) теперь выигрывают от реализации C, которая делает их такими же быстрыми, как обычные блокировки, и в 10-15 раз быстрее, чем их предыдущая реализация на чистом Python.

    (Предоставлено Антуаном Питру; bpo-3001.)

  • Алгоритм быстрого поиска в stringlib теперь используется методами split(), rsplit(), splitlines() и replace() для объектов bytes, bytearray и str. Аналогично, алгоритм также используется rfind(), rindex(), rsplit() и rpartition().

    (Исправление Florent Xicluna в bpo-7622 и bpo-7462.)

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

    (bpo-6713 Гавейна Болтона, Марка Дикинсона и Виктора Стиннера)

Было несколько других мелких оптимизаций. Разность наборов теперь выполняется быстрее, когда один операнд намного больше другого (исправление Андресса Беннетса в bpo-8685). Метод array.repeat() имеет более быструю реализацию (bpo-1569291 Александра Белопольского). BaseHTTPRequestHandler имеет более эффективную буферизацию (bpo-3709 от Эндрю Шаафа). Функция operator.attrgetter() была ускорена (bpo-10160 от Христа Георгиу). А ConfigParser немного быстрее загружает многострочные аргументы (bpo-7113 от Лукаша Ланги).

Юникод

Python обновлен до Юникод 6.0.0. Обновление стандарта добавляет более 2000 новых символов, включая символы emoji, важные для мобильных телефонов.

Кроме того, обновленный стандарт изменил свойства символов для двух символов каннада (Kannada) (U+0CF1, U+0CF2) и одного числового символа New Tai Lue (U+19DA), что сделало первые пригодными для использования в идентификаторах и дисквалифицировало последние. Дополнительные сведения см. в статье Изменения в базе данных символов Юникод.

Кодеки

Добавлена поддержка арабской кодировки DOS cp720 (bpo-1616979).

Кодирование MBCS больше не игнорирует аргумент обработчика ошибок. В строгом режиме по умолчанию он вызывает UnicodeDecodeError, когда встречает некодируемую последовательность байтов, и UnicodeEncodeError для некодируемого символа.

Кодек MBCS поддерживает обработчики ошибок 'strict' и 'ignore' для декодирования и 'strict' и 'replace' для кодирования.

Чтобы эмулировать кодировку Python3.1 MBCS, выберите обработчик 'ignore' для декодирования и обработчик 'replace' для кодирования.

В Mac OS X Python декодирует аргументы командной строки с 'utf-8', а не с кодировкой локали.

По умолчанию tarfile использует кодировку 'utf-8' в Windows (вместо 'mbcs') и обработчик ошибок 'surrogateescape' во всех операционных системах.

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

Документация продолжает улучшаться.

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

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

    Исходный код Lib/functools.py.

    (Предоставлено Рэймондом Хеттингером; см. rationale.)

  • Документы теперь содержат больше примеров и рецептов. В частности, модуль re имеет расширенный раздел Примеры регулярных выражений. Аналогично, модуль itertools продолжает обновляться новым Рецепты Itertools.

  • Модуль datetime теперь имеет вспомогательную реализацию на чистом Python. Функционал не изменился. Это просто обеспечивает более легкую для чтения альтернативную реализацию.

    (Предоставлено Александром Белопольским в bpo-9528.)

  • Неподдерживаемый каталог Demo был удален. Некоторые демо были интегрированы в документацию, некоторые перемещены в директорию Tools/demo, а некоторые вообще удалены.

    (Предоставлено Георгом Брандлом в bpo-7962.)

IDLE

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

    (Предоставлено Рэймондом Хеттингером; bpo-5150.)

  • IDLE в Mac OS X теперь работает как с Carbon AquaTk, так и с Cocoa AquaTk.

    (Предоставлено Кевином Уолцером, Недом Дейли и Рональдом Уссореном; bpo-6075.)

Репозиторий кода

В дополнение к существующему репозиторию кода Subversion по адресу http://svn.python.org теперь есть репозиторий Mercurial по адресу https://hg.python.org/.

После релиза 3.2 планируется перейти на Mercurial в качестве основного репозитория. Данная распределенная система управления версиями должна облегчить членам сообщества создание и совместное использование внешних наборов изменений. Подробности см. в PEP 385.

Чтобы научиться использовать новую систему управления версиями, см. Быстрый старт или Руководство по рабочим процессам Mercurial.

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

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

  • Сценарии idle, pydoc и 2to3 теперь устанавливаются с суффиксом для точной версии в make altinstall (bpo-10679).

  • Функции C, которые обращаются к базе данных Юникод, теперь принимают и возвращают символы из полного диапазона Юникод даже в узких сборках Юникод (Py_UNICODE_TOLOWER, Py_UNICODE_ISDECIMAL и других). Видимая разница в Python заключается в том, что unicodedata.numeric() теперь возвращает правильное значение для больших кодовых точек, а repr() может считать печатаемыми больше символов.

    (Сообщено Bupjoe Lee и исправлено Amaury Forgeot D’Arc; bpo-5127.)

  • Вычисляемые переходы теперь включены по умолчанию на поддерживаемых компиляторах (которые обнаруживаются скриптом configure). Их по-прежнему можно выборочно отключить, указав --without-computed-gotos.

    (Предоставлено Антуаном Питру; bpo-9203.)

  • Опция --with-wctype-functions удалена. Встроенная база данных юникода теперь используется для всех функций.

    (Предоставлено Амори Форжо Д’Арк; bpo-9210.)

  • Хэш-значения теперь являются значениями нового типа, Py_hash_t, который определяется как размер указателя. Ранее они имели тип long, который в некоторых 64-разрядных операционных системах по-прежнему имеет длину всего 32 бита. В результате этого исправления set и dict теперь могут содержать более 2**32 записей в сборках с 64-битными указателями (ранее они могли увеличиваться до такого размера, но их производительность катастрофически снижалась).

    (Предложено Рэймондом Хеттингером и реализовано Бенджамином Петерсоном; bpo-9778.)

  • Новый макрос Py_VA_COPY копирует состояние списка переменных аргументов. Он эквивалентен C99 va_copy, но доступен на всех платформах Python (bpo-2443).

  • Новая функция C API PySys_SetArgvEx() позволяет встроенному интерпретатору устанавливать sys.argv без изменения sys.path (bpo-5753).

  • PyEval_CallObject теперь доступен только в виде макроса. Объявление функции, которое было сохранено из соображений обратной совместимости, теперь удалено — макрос был представлен в 1997 году (bpo-8276).

  • Появилась новая функция PyLong_AsLongLongAndOverflow(), аналогичная PyLong_AsLongAndOverflow(). Оба они служат для преобразования Python int в собственный тип с фиксированной шириной, обеспечивая при этом обнаружение случаев, когда преобразование не подходит (bpo-7767).

  • Функция PyUnicode_CompareWithASCIIString() теперь возвращает не равно, если строка Python завершается NUL.

  • Существует новая функция PyErr_NewExceptionWithDoc(), похожая на PyErr_NewException(), но позволяющая указать строку документации. Это позволяет исключениям C иметь те же возможности самодокументирования, что и их чистые аналоги Python (bpo-7033).

  • При компиляции с параметром --with-valgrind распределитель pymalloc будет автоматически отключён при работе под Valgrind. Это дает улучшенное обнаружение утечек памяти при работе под Valgrind, а в других случаях использует преимущества pymalloc (bpo-2422).

  • Удалён формат O? из функций PyArg_Parse. Формат больше не используется и никогда не документировался (bpo-8837).

В C-API был внесен ряд других небольших изменений. Полный список см. в файле Misc/NEWS.

Кроме того, в сборку Mac OS X было внесено несколько обновлений, подробности см. в статье Mac/BuildScript/README.txt. Для пользователей, использующих 32/64-битную сборку, существует известная проблема с Tcl/Tk по умолчанию в Mac OS X 10.6. Соответственно, мы рекомендуем установить обновленную альтернативу, такую как ActiveState Tcl/Tk 8.5.9. См. https://www.python.org/download/mac/tcltk/ для получения дополнительной информации.

Портирование на Python 3.2

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

  • Модуль configparser имеет ряд исправлений. Основное изменение заключается в замене старого класса ConfigParser на давнюю предпочтительную альтернативу SafeConfigParser. Кроме того, есть ряд более мелких несовместимостей:

    • Синтаксис интерполяции теперь проверяется для операций get() и set(). В схеме интерполяции по умолчанию допустимы только две лексемы со знаками процента: %(name)s и %%, причем последний является экранированным знаком процента.
    • Методы set() и add_section() теперь проверяют, являются ли значения фактическими строками. Раньше неподдерживаемые типы могли быть введены непреднамеренно.
    • Повторяющиеся разделы или параметры из одного источника теперь поднимают DuplicateSectionError или DuplicateOptionError. Раньше дубликаты молча перезаписывали предыдущую запись.
    • Встроенные комментарии теперь отключены по умолчанию, поэтому теперь символ ; можно безопасно использовать в значениях.
    • Комментарии теперь могут иметь отступ. Следовательно, чтобы ; или # отображались в начале строки в многострочных значениях, их необходимо интерполировать. Благодаря этому символы префикса комментариев в значениях не будут ошибочно приняты за комментарии.
    • "" теперь является допустимым значением и больше не преобразуется автоматически в пустую строку. Для пустых строк используйте "option =" в строке.
  • Модуль nntplib был значительно переработан, а это означает, что его API часто несовместимы с API 3.1.

  • объекты bytearray больше нельзя использовать в качестве имён файлов; вместо этого их следует преобразовать в bytes.

  • array.tostring() и array.fromstring() были переименованы в array.tobytes() и array.frombytes() для ясности. Старые имена устарели. (См. bpo-8990.)

  • Функции PyArg_Parse*():

    • Формат «t#» удален: вместо него используйте «s#» или «s*»
    • Форматы «w» и «w#» были удалены: вместо них используйте «w*»
  • Тип PyCObject, объявленный устаревшим в версии 3.1, удален. Чтобы обернуть непрозрачные указатели C в объекты Python, вместо этого следует использовать API PyCapsule; новый тип имеет четко определённый интерфейс для передачи информации о безопасности ввода и менее сложную сигнатуру для вызова деструктора.

  • Функция sys.setfilesystemencoding() была удалена из-за несовершенного дизайна.

  • Функция и метод random.seed() теперь содержат начальные строки с хэш-функцией sha512. Чтобы получить доступ к предыдущей версии seed для воспроизведения последовательностей Python 3.1, устанавливает для аргумента version значение 1, random.seed(s, version=1).

    Ранее устаревшая функция string.maketrans() была удалена в пользу статических методов bytes.maketrans() и bytearray.maketrans(). Это изменение устраняет путаницу, связанную с тем, какие типы поддерживаются модулем string. Теперь str, bytes и bytearray имеют собственные методы maketrans и translate с промежуточными таблицами перевода соответствующего типа.

    (Предоставлено Георгом Брандлом; bpo-5675.)

  • Ранее устаревшая функция contextlib.nested() была удалена в пользу простого оператора with, которая может принимать несколько менеджеров контекста. Последний метод быстрее (поскольку он встроен) и лучше справляется с завершением нескольких менеджеров контекста, когда один из них вызывает исключение:

    with open('mylog.txt') as infile, open('a.out', 'w') as outfile:
        for line in infile:
            if '<critical>' in line:
                outfile.write(line)
    

    (Предоставлено Георгом Брандлом и Маттиасом Брандстрёмом; appspot issue 53094.)

  • struct.pack() теперь допускает только байты для строкового кода пакета s. Раньше он принимал текстовые аргументы и неявно кодировал их в байты, используя UTF-8. Это было проблематично, потому что оно делало предположения о правильном кодировании и потому, что кодирование переменной длины может дать сбой при записи в сегмент фиксированной длины структуры.

    Такой код, как struct.pack('<6sHHBBB', 'GIF87a', x, y), следует переписать с использованием байтов вместо текста, struct.pack('<6sHHBBB', b'GIF87a', x, y).

    (Обнаружен Дэвидом Бизли и исправлен Виктором Стиннером; bpo-10783.)

  • Класс xml.etree.ElementTree теперь вызывает xml.etree.ElementTree.ParseError при сбое парсинга. Ранее он поднимал xml.parsers.expat.ExpatError.

  • Новое, более длинное значение str() для чисел с плавающей запятой может сломать доктесты, основанное на старом формате вывода.

  • В subprocess.Popen значением по умолчанию для close_fds теперь является True в Unix; под Windows это True, если три стандартных потока установлены на None, в противном случае False. Раньше close_fds всегда был False по умолчанию, что приводило к трудным для устранения ошибкам или состояниям гонки, когда дескрипторы открытых файлов просачивались в дочерний процесс.

  • Поддержка устаревшего HTTP 0.9 удалена из urllib.request и http.client. Такая поддержка все ещё присутствует на стороне сервера (в http.server).

    (Предоставлено Антуаном Питру, bpo-10711.)

  • Сокеты SSL в режиме тайм-аута теперь вызывают socket.timeout, когда происходит тайм-аут, а не общий SSLError.

    (Предоставлено Антуаном Питру, bpo-10272.)

  • Вводящие в заблуждение функции PyEval_AcquireLock() и PyEval_ReleaseLock() официально объявлены устаревшими. Вместо этого следует использовать API-интерфейсы с информацией о состоянии потока (например, PyEval_SaveThread() и PyEval_RestoreThread()).

  • Из-за угроз безопасности asyncore.handle_accept() устарел, и вместо него была добавлена новая функция asyncore.handle_accepted().

    (Предоставлено Джампаоло Родола в bpo-6706.)

  • Из-за новой реализации GIL PyEval_InitThreads() больше нельзя вызывать перед Py_Initialize().