Содержание страницы
Что нового в Python 3.2¶What’s New In Python 3.2
| Автор: | Рэймонд Хеттингер |
|---|
В этой статье описаны новые возможности Python 3.2 по сравнению с версией 3.1. Она сосредоточена на нескольких ключевых моментах и приводит несколько примеров. Полные сведения см. в файле Misc/NEWS.
См. также
PEP 392 - График выпуска Python 3.2
PEP 384: Определение стабильного ABI¶PEP 384: Defining a Stable ABI
Раньше модули расширения, собранные для одной версии Python, часто были несовместимы с другими версиями. Особенно в Windows каждый выпуск с новыми возможностями требовал пересборки всех модулей расширения, которые хотелось использовать. Это было следствием свободного доступа к внутренним структурам интерпретатора Python, который могли использовать модули расширения.
В Python 3.2 появляется альтернативный подход: модули расширения, ограничивающие себя ограниченным API (определяя Py_LIMITED_API), не могут использовать многие внутренние структуры, но ограничены набором функций API, которые обещают быть стабильными на протяжении нескольких выпусков. В результате модули расширения, собранные для 3.2 в этом режиме, будут также работать с 3.3, 3.4 и так далее. Модули расширения, использующие детали структур памяти, по-прежнему можно собирать, но их придётся перекомпилировать для каждого выпуска с новыми возможностями.
См. также
- PEP 384 - Определение стабильного ABI
- PEP написан Мартином фон Лёвисом.
PEP 389: Модуль разбора командной строки argparse¶PEP 389: Argparse Command Line Parsing Module
Новый модуль для разбора командной строки, 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', # имя переменной, используемое в сообщении справки
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 # задать параметры движения
См. также
- PEP 389 - Новый модуль разбора командной строки
- PEP написан Стивеном Бетардом.
Обновление кода optparse за подробностями о различиях с optparse.
PEP 391: Конфигурация логирования на основе словарей¶PEP 391: Dictionary Based Configuration for Logging
Модуль 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¶PEP 3148: The concurrent.futures module
Код для создания параллельного выполнения и управления им собирается в новом пространстве имён верхнего уровня concurrent. Первый его компонент – пакет futures, предоставляющий единый высокоуровневый интерфейс для управления потоками и процессами.
Дизайн concurrent.futures был вдохновлён пакетом java.util.concurrent. В этой модели выполняющийся вызов и его результат представлены объектом Future, который абстрагирует общие для потоков, процессов и удалённых вызовов возможности. Этот объект поддерживает проверку состояния (выполняется или завершён), таймауты, отмены, добавление колбэков и доступ к результатам или исключениям.
Основная часть нового модуля – два класса исполнителей для запуска и управления вызовами. Цель исполнителей – упростить использование существующих инструментов для параллельных вызовов. Они избавляют от необходимости настраивать пул ресурсов, запускать вызовы, создавать очередь результатов, добавлять обработку таймаутов и ограничивать общее количество потоков, процессов или удалённых вызовов.
В идеале каждое приложение должно использовать один общий исполнитель для нескольких компонентов, чтобы ограничения на процессы и потоки управлялись централизованно. Это решает проблему проектирования, возникающую, когда у каждого компонента своя конкурирующая стратегия управления ресурсами.
Оба класса имеют общий интерфейс с тремя методами:
submit() для планирования вызываемого объекта и возврата объекта Future;
map() для планирования нескольких асинхронных вызовов одновременно и shutdown() для освобождения ресурсов. Класс является контекстным менеджером и может использоваться в операторе with, чтобы гарантировать автоматическое освобождение ресурсов после завершения всех ожидающих future.
Простой пример 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¶PEP 3147: PYC Repository Directories
Схема кэширования байт-кода 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: .so-файлы с тегом версии ABI¶PEP 3149: ABI Version Tagged .so Files
Директория репозитория PYC позволяет размещать несколько кэшированных файлов байт-кода в одном месте. Этот PEP реализует аналогичный механизм для разделяемых объектных файлов, помещая их в общую директорию с разными именами для каждой версии.
Общая директория называется «pyshared», а имена файлов различаются указанием реализации Python (например, CPython, PyPy, Jython и т.д.), номерами старшей и младшей версии, а также необязательными флагами сборки (например, «d» для отладки, «m» для pymalloc, «u» для wide-unicode). Для произвольного пакета «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 – файлы .so с тегами версии ABI
- PEP написан Барри Варшавой.
PEP 3333: Python Web Server Gateway Interface 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()и environ должны использовать нативные строки. Их нельзя смешивать.
Для разработчиков серверов, пишущих CGI-to-WSGI мосты или другие протоколы в стиле CGI, пользователи должны иметь возможность доступа к окружению через нативные строки, даже если базовая платформа использует другую конвенцию. Для преодоления этого разрыва в модуле wsgiref появилась новая функция wsgiref.handlers.read_environ() для перекодирования CGI-переменных из os.environ в нативные строки и возврата нового словаря.
См. также
- PEP 3333 – Python Web Server Gateway Interface v1.0.1
- PEP написан Филлипом Иби.
Прочие изменения языка ¶Other Language Changes
Некоторые небольшие изменения, внесённые в ядро языка Python:
Форматирование строк для
format()иstr.format()получило новые возможности для символа формата #. Ранее для целых чисел в двоичной, восьмеричной или шестнадцатеричной системе он добавлял префикс «0b», «0o» или «0x» соответственно. Теперь он также может обрабатывать числа с плавающей точкой, комплексные числа и Decimal, при этом вывод всегда содержит десятичную точку, даже если после неё нет цифр.>>> 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
Теперь это разрешено. Помните, что цель (target) в предложении
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теперь создаёт подклассы tuple. Это означает, что структуры C, такие как возвращаемыеos.stat(),time.gmtime()иsys.version_info, теперь работают как именованный кортеж и работают с функциями и методами, ожидающими tuple в качестве аргумента. Это большой шаг вперёд в обеспечении гибкости структур 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)'
(Предложено Arfrever Frehtes Taifersar Arahesis и реализовано Benjamin Peterson в bpo-8413.)
Теперь предупреждениями проще управлять с помощью переменной окружения
PYTHONWARNINGSв качестве альтернативы использованию-Wв командной строке:$ export PYTHONWARNINGS='ignore::RuntimeWarning::,once::UnicodeWarning::'
(Предложено Barry Warsaw и реализовано Philip Jenvey в 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'>
(Добавлено Antoine Pitrou и Georg Brandl в 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)
(Вклад Daniel Stutzbach в bpo-9213, Alexander Belopolsky в bpo-2690 и Nick Coghlan в bpo-10889.)
Встроенная функция
callable()из Py2.x была восстановлена. Она предоставляет краткую и читаемую альтернативу использованию абстрактного базового класса в выражении видаisinstance(x, collections.Callable):>>> callable(max) True >>> callable(20) False
(См. bpo-10518.)
Механизм импорта Python теперь может загружать модули, установленные в каталогах, в именах путей которых есть не-ASCII символы. Это решило давнюю проблему с домашними каталогами пользователей, имеющих не-ASCII символы в именах.
(Потребовало значительной работы от Victor Stinner в bpo-9425.)
Новые, улучшенные и устаревшие модули¶New, Improved, and Deprecated Modules
Стандартная библиотека Python прошла значительную работу по сопровождению и улучшению качества.
Самая важная новость для Python 3.2: пакет email, модуль mailbox и модули nntplib теперь корректно работают с моделью байты/текст в Python 3. Впервые правильно обрабатываются сообщения со смешанными кодировками.
По всей стандартной библиотеке уделено больше внимания вопросам кодировок и различиям между текстом и байтами. В частности, взаимодействие с операционной системой теперь лучше обменивается не-ASCII данными, используя кодировку Windows MBCS, локаль-зависимые кодировки или UTF-8.
Ещё одно важное достижение – добавление значительно улучшенной поддержки SSL-соединений и сертификатов безопасности.
Кроме того, больше классов теперь реализуют менеджер контекста для удобной и надёжной очистки ресурсов с помощью оператора with.
email¶
Пригодность к использованию пакета email в Python 3 в значительной степени исправлена благодаря масштабной работе R. David Murray. Проблема заключалась в том, что электронные письма обычно читаются и хранятся в виде 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.Класс
smtplibSMTPтеперь принимает байтовую строку для аргумента msg методаsendmail(), а новый методsend_message()принимает объектMessageи может опционально получать адреса from_addr и to_addrs непосредственно из объекта.
(Предложено и реализовано R. David Murray, bpo-4661 и bpo-10321.)
elementtree¶
Пакет xml.etree.ElementTree и его аналог xml.etree.cElementTree обновлены до версии 1.3.
Добавлено несколько новых полезных функций и методов:
xml.etree.ElementTree.fromstringlist()– строит XML-документ из последовательности фрагментовxml.etree.ElementTree.register_namespace()– для регистрации глобального префикса пространства имёнxml.etree.ElementTree.tostringlist()для строкового представления, включая все подспискиxml.etree.ElementTree.Element.extend()для добавления последовательности из нуля или более элементовxml.etree.ElementTree.Element.iterfind()ищет элемент и подэлементыxml.etree.ElementTree.Element.itertext()создаёт текстовый итератор по элементу и его подэлементамxml.etree.ElementTree.TreeBuilder.end()закрывает текущий элементxml.etree.ElementTree.TreeBuilder.doctype()обрабатывает объявление doctype
Два метода устарели:
xml.etree.ElementTree.getchildren()используйтеlist(elem).xml.etree.ElementTree.getiterator()используйтеElement.iter.
Подробнее об обновлении см. в статье Introducing ElementTree на сайте Фредрика Лунда.
(Авторы: Florent Xicluna и Fredrik Lundh, 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)
Если таблица phonelist обновляется, устаревшее содержимое кеша можно очистить с помощью:
>>> get_phone_number.cache_clear()
(Автор: Raymond Hettinger с использованием идей дизайна от Jim Baker, Miki Tebeka и Nick Coghlan; см. recipe 498245, recipe 577479, bpo-10586 и bpo-10593.)
Декоратор
functools.wraps()теперь добавляет атрибут__wrapped__, указывающий на исходную вызываемую функцию. Это позволяет проводить интроспекцию обёрнутых функций. Он также копирует__annotations__, если тот определён. Кроме того, он корректно пропускает отсутствующие атрибуты, такие как__doc__, которые могут быть не определены для обёрнутой вызываемой функции.В приведённом выше примере кеш можно удалить, восстановив исходную функцию:
>>> get_phone_number = get_phone_number.__wrapped__ # некэшированная функция
(Авторы: Nick Coghlan и Terrence Cole; 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 остальные методы сравнения заполняются автоматически.
(Автор: Raymond Hettinger.)
Чтобы облегчить перенос программ с Python 2, функция
functools.cmp_to_key()преобразует устаревшую функцию сравнения в современную функцию ключа:>>> # порядок сортировки с учётом локали >>> sorted(iterable, key=cmp_to_key(locale.strcoll)) # doctest: +SKIP
Примеры сортировки и краткое руководство по сортировке см. в руководстве Sorting HowTo.
(Автор: Raymond Hettinger.)
itertools¶
Модуль
itertoolsсодержит новую функциюaccumulate(), созданную по образцу оператора scan из APL и функции accumulate из Numpy:>>> 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.(Автор: Raymond Hettinger с учётом предложений по дизайну от Mark Dickinson.)
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})
(Автор: Raymond Hettinger.)
Класс
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']
(Автор: Raymond Hettinger.)
У класса
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'])
(Автор: Raymond Hettinger.)
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(), но после пересечения точки барьера потоки остаются живыми и продолжают работать (подсчитывать бюллетени).
Если какая-либо из предшествующих задач может зависнуть или задержаться, барьер можно создать с необязательным параметром тайм-аут. Тогда, если период ожидания истекает до того, как все предшествующие задачи достигнут точки барьера, все ожидающие потоки освобождаются и возбуждается исключение 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)
В этом примере барьер обеспечивает более надежное правило. Если некоторые избирательные участки не заканчивают работу до полуночи, барьер срабатывает по тайм-ауту, и бюллетени опечатываются и помещаются в очередь для последующей обработки.
Смотрите Barrier Synchronization Patterns для получения дополнительных примеров использования барьеров в параллельных вычислениях. Кроме того, простое и подробное объяснение барьеров приведено в The Little Book of Semaphores, раздел 3.6.
(Автор: Kristján Valur Jónsson, рецензирование API: Jeffrey Yasskin, в bpo-8777.)
datetime and time¶
В модуле
datetimeпоявился новый типtimezone, который реализует интерфейсtzinfo, возвращая фиксированное смещение UTC и название часового пояса. Это упрощает создание объектов datetime с учётом часового пояса:>>> 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, регламентирующим формат%ystrptime.Начиная с 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имеет значение false, функцияtime.asctime()принимает любой год, помещающийся в int в C, а функцииtime.mktime()иtime.strftime()принимают полный диапазон, поддерживаемый соответствующими функциями операционной системы.
(Авторы: Alexander Belopolsky и Victor Stinner в bpo-1289118, bpo-5094, bpo-6641, bpo-2706, bpo-1777412, bpo-8013 и bpo-10827.)
math¶
Модуль math обновлён и содержит шесть новых функций, вдохновлённых стандартом C99.
Функция isfinite() предоставляет надёжный и быстрый способ обнаружения особых значений. Она возвращает True для обычных чисел и False для NaN или бесконечность:
>>> 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) # более точный способ вычисления e**x-1 для малых x
0.013765762467652909
Функция erf() вычисляет интеграл вероятности или функцию ошибок Гаусса. Дополнительная функция ошибок, erfc(), равна 1 - erf(x):
>>> from math import erf, erfc, sqrt
>>> erf(1.0/sqrt(2.0)) # доля нормального распределения в пределах одного стандартного отклонения
0.682689492137086
>>> erfc(1.0/sqrt(2.0)) # доля нормального распределения за пределами одного стандартного отклонения
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) # логарифм факториала 800
4551.950730698041
(Автор: Mark Dickinson.)
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):
...
(Патч предоставлен Daniel Urban; 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'>
logging¶
В дополнение к конфигурации на основе словаря, описанной выше, пакет 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: {}'.format(name))
yield
logging.info('Exiting: {}'.format(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.)
decimal and fractions¶
Марк Дикинсон разработал элегантную и эффективную схему, гарантирующую, что разные числовые типы данных будут иметь одинаковое хеш-значение, когда их фактические значения равны (bpo-8188):
assert hash(Fraction(3, 2)) == hash(1.5) == \
hash(Decimal("1.5")) == hash(complex(1.5, 0))
Некоторые детали хеширования доступны через новый атрибут sys.hash_info, который описывает разрядность хеш-значения, простой модуль, хеш-значения для бесконечности и 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).
(Авторы: Mark Dickinson и Raymond Hettinger.)
ftp¶
Класс 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)
(Авторы: Tarek Ziadé и Giampaolo Rodolà в bpo-4972, и Georg Brandl в bpo-8046 и bpo-1286.)
Класс FTP_TLS теперь принимает параметр context, который является
объектом ssl.SSLContext, позволяющим объединять параметры конфигурации SSL,
сертификаты и закрытые ключи в единую (потенциально долгоживущую) структуру.
(Автор: Giampaolo Rodolà; bpo-8806.)
popen¶
Функции os.popen() и subprocess.Popen() теперь поддерживают
операторы with для автоматического закрытия файловых дескрипторов.
(Авторы: Antoine Pitrou и Brian Curtin в bpo-7461 и bpo-10554.)
select¶
Модуль select теперь предоставляет новый константный атрибут,
PIPE_BUF, который указывает минимальное количество байтов, которые
гарантированно не будут блокироваться, когда select.select() сообщает, что канал
готов к записи.
>>> import select
>>> select.PIPE_BUF
512
(Доступно в системах Unix. Патч от Sébastien Sablé в bpo-9862)
gzip и zipfile¶gzip and 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'
(Авторы: Anand B. Pillai в bpo-3488; и Antoine Pitrou, Nir Aides и Brian Curtin в 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
(Предложено Tarek Ziadé и реализовано Lars Gustäbel в 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'}
(Предложено Carl Chenet в 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.
(Автор: Victor Stinner.)
shutil¶
Функция shutil.copytree() теперь имеет две новые опции:
- ignore_dangling_symlinks: когда
symlinks=False, чтобы функция копировала файл, на который указывает символьная ссылка, а не саму ссылку. Эта опция подавляет ошибку, возникающую, если файл не существует. - copy_function: вызываемый объект, используемый для копирования файлов. По умолчанию используется
shutil.copy2().
(Автор: Tarek Ziadé.)
Кроме того, модуль shutil теперь поддерживает архивацию для zip-архивов, несжатых tar-архивов, tar-архивов со сжатием gzip и tar-архивов со сжатием bzip2. Также появились функции для регистрации дополнительных форматов архивов (например, 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') # перейти к распаковке
>>> 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'
... )
(Автор: Tarek Ziadé.)
sqlite3¶
Модуль sqlite3 обновлён до версии pysqlite 2.6.0. У него появились две новые возможности.
- Атрибут
sqlite3.Connection.in_transitистинен, если есть активная транзакция для незафиксированных изменений. - Методы
sqlite3.Connection.enable_load_extension()иsqlite3.Connection.load_extension()позволяют загружать расширения SQLite из файлов «.so». Одним из известных расширений является расширение полнотекстового поиска, распространяемое с SQLite.
(Авторы: R. David Murray и Shashwat Anand; bpo-8845.)
html¶
Появился новый модуль html с единственной функцией escape(), которая используется для экранирования зарезервированных символов в HTML-разметке:
>>> import html
>>> html.escape('x > 2 && x < 7')
'x > 2 && x < 7'
socket¶
В модуль socket внесены два улучшения.
- У объектов сокетов появился метод
detach(), который переводит сокет в закрытое состояние, не закрывая фактически базовый файловый дескриптор. Последний затем можно использовать для других целей. (Добавлено Antoine Pitrou; bpo-8524.) socket.create_connection()теперь поддерживает протокол управления контекстом для безусловного поглощения исключенийsocket.errorи закрытия сокета по завершении. (Автор: Giampaolo Rodolà; 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.)
nntp¶
Модуль nntplib получил переработанную реализацию с улучшенной семантикой байтов и текста, а также более практичными API. Эти изменения нарушают совместимость с версией nntplib из Python 3.1, которая и сама по себе была частично неработоспособна.
Также добавлена поддержка защищённых соединений как через неявный (с использованием nntplib.NNTP_SSL), так и через явный (с использованием nntplib.NNTP.starttls()) TLS.
(Предложено Антуаном Питру в bpo-9360 и Эндрю Вантом в bpo-1926.)
сертификаты¶certificates
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 – кортеж (host, port), указывающий, откуда устанавливается HTTP-соединение.
Поддержка проверки сертификатов и виртуальных хостов HTTPS была добавлена в HTTPSConnection.
Метод 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
(Предложено Michael Foord.)
Экспериментирование в интерактивной оболочке стало проще, поскольку класс
unittest.case.TestCaseтеперь можно создавать без аргументов:>>> from unittest import TestCase >>> TestCase().assertEqual(pow(2, 3), 8)
(Предложено Michael Foord.)
Модуль
unittestсодержит два новых метода,assertWarns()иassertWarnsRegex(), для проверки того, что заданный тип предупреждения вызывается тестируемым кодом:with self.assertWarns(DeprecationWarning): legacy_function('XYZ')
(Предложено Антуаном Питру, bpo-9754.)
Ещё один новый метод,
assertCountEqual(), используется для сравнения двух итерируемых объектов с целью определить, равны ли их количества элементов (присутствуют ли одни и те же элементы с одинаковым числом вхождений независимо от порядка):def test_anagram(self): self.assertCountEqual('algorithm', 'logarithm')
(Автор: Raymond Hettinger.)
Одна из основных особенностей модуля unittest – стремление выдавать содержательные диагностические сообщения при сбое теста. По возможности сбой записывается вместе с diff вывода. Это особенно полезно при анализе журналов неудачных тестовых запусков. Однако, поскольку diff может быть объёмным, появился новый атрибут
maxDiff, задающий максимальную длину отображаемого diff.Кроме того, имена методов в модуле были приведены в порядок.
Например,
assertRegex()– новое имя дляassertRegexpMatches(), которое было названо неправильно, потому что тест используетre.search(), а неre.match(). Другие методы, использующие регулярные выражения, теперь именуются с использованием краткой формы «Regex» вместо «Regexp» – это соответствует именам, используемым в других реализациях unittest, соответствует старому названию модуляreв Python и имеет однозначный верблюжий регистр.(Предложено Raymond Hettinger; реализовано Ezio Melotti.)
Чтобы повысить согласованность, некоторые давно существующие псевдонимы методов объявляются устаревшими; вместо них следует использовать предпочтительные имена:
Старое имя Предпочтительное имя assert_()assertTrue()assertEquals()assertEqual()assertNotEquals()assertNotEqual()assertAlmostEquals()assertAlmostEqual()assertNotAlmostEquals()assertNotAlmostEqual()Аналогично, методы
TestCase.fail*, объявленные устаревшими в Python 3.1, предположительно будут удалены в Python 3.3. Также см. раздел Устаревшие псевдонимы в документацииunittest.(Предложено Ezio Melotti; bpo-9424.)
Метод
assertDictContainsSubset()был объявлен устаревшим, потому что он был реализован с ошибкой: аргументы передавались в неправильном порядке. Это создавало трудно отлаживаемые оптические иллюзии, когда тесты вродеTestCase().assertDictContainsSubset({'a':1, 'b':2}, {'a':1})завершались неудачей.(Автор: Raymond Hettinger.)
random¶
Целочисленные методы модуля random теперь лучше генерируют равномерные распределения. Раньше они вычисляли выборки с помощью int(n*random()), что давало небольшое смещение, когда n не было степенью двойки. Теперь производится несколько выборок из диапазона, размер которого равен ближайшей степени двойки, и выборка сохраняется только если она попадает в диапазон 0 <= x < n. Затронутые функции и методы: randrange(), randint(), choice(), shuffle() и sample().
(Предложено Raymond Hettinger; bpo-9025.)
poplib¶
Класс POP3_SSL теперь принимает параметр контекст, который является объектом ssl.SSLContext, позволяющим объединять параметры настройки SSL, сертификаты и закрытые ключи в единую (потенциально долгоживущую) структуру.
(Предложено Giampaolo Rodolà; bpo-8807.)
asyncore¶
asyncore.dispatcher теперь предоставляет метод handle_accepted(), возвращающий пару (sock, addr), которая вызывается при фактическом установлении соединения с новым удаленным узлом. Предполагается, что это будет использоваться как замена старому handle_accept() и избавляет пользователя от необходимости вызывать accept() напрямую.
(Предложено Giampaolo Rodolà; bpo-6706.)
tempfile¶
Модуль tempfile теперь содержит новый менеджер контекста TemporaryDirectory, который обеспечивает простое детерминированное удаление временных каталогов:
with tempfile.TemporaryDirectory() as tmpdirname:
print('created temporary dir:', tmpdirname)
(Предложено Neil Schemenauer и Nick Coghlan; 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'
(Предложено Rodolpho Eckhardt и Nick Coghlan; 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>
(Предложено Michael Foord.)
pydoc¶
Модуль pydoc теперь предоставляет значительно улучшенный интерфейс веб-сервера, а также новую опцию командной строки -b для автоматического открытия окна браузера для отображения этого сервера:
$ pydoc3.2 -b
(Предложено Ron Adam; 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, и позволяют самому увидеть, что делает синтаксис языка «под капотом».
(Предложено Nick Coghlan; 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'
Удобно, что часть функциональности site доступна напрямую из командной строки:
$ 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. Поддержка
inline-комментариев теперь по умолчанию отключена, а дубликаты секций или опций
не допускаются в одном источнике конфигурации.
Парсеры конфигураций получили новый 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-функций или чтение напрямую из словарей и строк.
(Все изменения предоставлены Łukasz Langa.)
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'
Как подробно описано в Parsing ASCII Encoded Bytes, все функции 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'')
(Работа Nick Coghlan, Dan Mahn и Senthil Kumaran в bpo-2987, bpo-5468 и bpo-9873.)
mailbox¶
Благодаря согласованным усилиям R. David Murray, модуль mailbox был
исправлен для Python 3.2. Сложность заключалась в том, что mailbox изначально
был спроектирован с текстовым интерфейсом, но email-сообщения лучше представлять с помощью
bytes, поскольку различные части сообщения могут иметь разные кодировки.
Решение использовало двоичную поддержку пакета email для разбора
произвольных email-сообщений. Кроме того, решение потребовало ряда изменений
API.
Как и ожидалось, метод add() для
объектов mailbox.Mailbox теперь принимает двоичные входные данные.
StringIO и ввод из текстового файла устарели. Кроме того, строковый ввод
будет выдавать ошибку на раннем этапе, если используются не-ASCII символы. Ранее ошибка возникала при
обработке email на более позднем шаге.
Также поддерживается двоичный вывод. Метод get_file()
теперь возвращает файл в двоичном режиме (ранее он некорректно устанавливал
файл в текстовый режим). Также появился новый метод get_bytes(),
который возвращает bytes-представление сообщения, соответствующего
заданному ключу.
Всё ещё возможно получить недвоичный вывод, используя метод get_string()
старого API, но такой подход
не очень полезен. Вместо этого лучше извлекать сообщения из
объекта Message или загружать их из двоичного ввода.
(Предоставлено R. David Murray, при участии Steffen Daode Nurpmeso и начального патча от Victor Stinner в bpo-9124.)
turtledemo¶
Демонстрационный код для модуля turtle был перенесён из каталога Demo
в основную библиотеку. Он включает более десятка примеров скриптов с
наглядными демонстрациями. Находясь в sys.path, его теперь можно запускать напрямую
из командной строки:
$ python -m turtledemo
(Перенесён из каталога Demo Alexander Belopolsky в bpo-10199.)
Многопоточность¶Multi-threading
Механизм сериализации выполнения одновременно работающих потоков Python (обычно известный как GIL или Глобальная блокировка интерпретатора) был переписан. Среди целей были более предсказуемые интервалы переключения и уменьшение накладных расходов из-за конкуренции за блокировку и количества последующих системных вызовов. Понятие «интервал проверки» для разрешения переключения потоков было отброшено и заменено абсолютной длительностью, выраженной в секундах. Этот параметр настраивается через
sys.setswitchinterval(). В настоящее время по умолчанию он равен 5 миллисекундам.Дополнительные сведения о реализации можно прочитать в сообщении в списке рассылки python-dev (однако, «приоритетные запросы», как описано в этом сообщении, не были сохранены для включения).
(Предоставлено Antoine Pitrou.)
Обычные и рекурсивные блокировки теперь принимают необязательный аргумент timeout для своего метода
acquire(). (Предоставлено Antoine Pitrou; bpo-7316.)Аналогично,
threading.Semaphore.acquire()также получил аргумент timeout. (Предоставлено Torsten Landschoff; bpo-850728.)Обычные и рекурсивные захваты блокировки теперь можно прерывать сигналами на платформах, использующих Pthreads. Это означает, что программы Python, которые взаимоблокируются при захвате блокировок, можно успешно завершить, многократно отправляя процессу SIGINT (нажав Ctrl+C в большинстве оболочек). (Автор: Reid Kleckner; bpo-8844.)
Оптимизации¶Optimizations
Добавлено несколько небольших улучшений производительности:
Оптимизатор «глазка» Python теперь распознает шаблоны, такие как
x in {1, 2, 3}, как проверку принадлежности к набору констант. Оптимизатор перестраиваетsetвfrozensetи сохраняет предварительно построенную константу.Теперь, когда замедление устранено, стало практичным начать писать проверки принадлежности с использованием set-нотации. Этот стиль одновременно ясен семантически и быстр в работе:
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равен true.(Предоставлено Антуаном Питру в 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().Преобразования целых чисел в строки теперь работают с двумя «цифрами» за раз, сокращая количество операций деления и взятия остатка.
(bpo-6713 от Гавейна Болтона, Марка Дикинсона и Виктора Стиннера.)
Было сделано несколько других незначительных оптимизаций. Разность множеств теперь работает быстрее, когда один операнд намного больше другого (патч от Андреса Беннетта в bpo-8685). Метод array.repeat() получил более быструю реализацию (bpo-1569291 от Александра Белопольского). BaseHTTPRequestHandler имеет более эффективную буферизацию (bpo-3709 от Эндрю Шаафа). Функция operator.attrgetter() была ускорена (bpo-10160 от Христоса Георгиу). И ConfigParser загружает многострочные аргументы немного быстрее (bpo-7113 от Лукаша Ланги).
Юникод¶Unicode
Python был обновлён до Unicode 6.0.0. Обновление стандарта добавляет более 2000 новых символов, включая эмодзи, которые важны для мобильных телефонов.
Кроме того, обновлённый стандарт изменил свойства символов для двух символов каннада (U+0CF1, U+0CF2) и одного числового символа New Tai Lue (U+19DA), сделав первые допустимыми для использования в идентификаторах, а последний – недопустимым. Подробнее см. Unicode Character Database Changes.
Кодеки¶Codecs
Добавлена поддержка арабской DOS-кодировки cp720 (bpo-1616979).
Кодировка MBCS больше не игнорирует аргумент обработчика ошибок. В режиме строгой обработки по умолчанию она возбуждает UnicodeDecodeError при обнаружении не декодируемой последовательности байтов и UnicodeEncodeError для не кодируемого символа.
Кодек MBCS поддерживает обработчики ошибок 'strict' и 'ignore' для декодирования, и 'strict' и 'replace' для кодирования.
Для эмуляции кодировки MBCS Python 3.1 выберите обработчик 'ignore' для декодирования и 'replace' для кодирования.
На Mac OS X Python декодирует аргументы командной строки с помощью 'utf-8', а не кодировки локали.
По умолчанию tarfile использует кодировку 'utf-8' в Windows (вместо 'mbcs') и обработчик ошибок 'surrogateescape' на всех операционных системах.
Документация¶Documentation
Документация продолжает улучшаться.
Таблица быстрых ссылок добавлена в начало длинных разделов, таких как Встроенные функции. В случае с
itertoolsссылки сопровождаются таблицами сводок в стиле шпаргалок, чтобы дать обзор и освежить память без необходимости читать всю документацию.В некоторых случаях чистый исходный код на Python может быть полезным дополнением к документации, поэтому теперь многие модули имеют быстрые ссылки на последнюю версию исходного кода. Например, документация модуля
functoolsимеет быструю ссылку вверху с пометкой:Исходный код Lib/functools.py.
(Автор: Raymond Hettinger; см. обоснование.)
Документация теперь содержит больше примеров и рецептов. В частности, в модуле
reесть обширный раздел «Примеры регулярных выражений». Точно так же модульitertoolsпродолжает пополняться новыми «Рецептами itertools».Модуль
datetimeтеперь имеет вспомогательную реализацию на чистом Python. Функциональность не изменилась. Это просто предоставляет более читабельную альтернативную реализацию.(Автор: Alexander Belopolsky; bpo-9528.)
Необслуживаемый каталог
Demoбыл удалён. Некоторые демонстрационные примеры были включены в документацию, некоторые перемещены в каталогTools/demo, а остальные удалены полностью.(Автор: Georg Brandl; bpo-7962.)
IDLE¶
Репозиторий кода¶Code Repository
В дополнение к существующему репозиторию Subversion по адресу http://svn.python.org теперь также доступен репозиторий Mercurial по адресу https://hg.python.org/.
После выхода версии 3.2 планируется перейти на Mercurial в качестве основного репозитория. Эта распределённая система управления версиями должна упростить членам сообщества создание и обмен внешними наборами изменений. Подробнее см. PEP 385.
Чтобы научиться пользоваться новой системой контроля версий, посмотрите учебник Джоэла Спольски или Руководство по рабочим процессам в Mercurial.
Изменения в сборке и C API¶Build and C API Changes
Изменения процесса сборки Python и C API включают:
Сценарии idle, pydoc и 2to3 теперь устанавливаются с суффиксом, соответствующим версии, на
make altinstall(bpo-10679).C-функции, обращающиеся к базе данных Unicode, теперь принимают и возвращают символы из всего диапазона Unicode, даже в сборках с узкими юникодными строками (Py_UNICODE_TOLOWER, Py_UNICODE_ISDECIMAL и другие). Видимое различие в Python заключается в том, что
unicodedata.numeric()теперь возвращает корректное значение для больших кодовых точек, аrepr()может считать больше символов печатаемыми.(Сообщил Bupjoe Lee, исправил Amaury Forgeot D’Arc; bpo-5127.)
Вычисляемые переходы (computed gotos) теперь включены по умолчанию на поддерживаемых компиляторах (которые обнаруживаются сценарием configure). Их по-прежнему можно выборочно отключить, указав
--without-computed-gotos.(Автор: Antoine Pitrou; bpo-9203.)
Опция
--with-wctype-functionsбыла удалена. Встроенная база данных Unicode теперь используется для всех функций.(Автор: Amaury Forgeot D’Arc; bpo-9210.)
Хеш-значения теперь являются значениями нового типа,
Py_hash_t, который определён как имеющий тот же размер, что и указатель. Ранее они были типа long, который на некоторых 64-битных операционных системах всё ещё имеет длину всего 32 бита. В результате этого исправленияsetиdictтеперь могут содержать более2**32записей в сборках с 64-битными указателями (ранее они могли вырасти до такого размера, но их производительность катастрофически падала).(Предложено Raymond Hettinger, реализовано Benjamin Peterson; bpo-9778.)
Новый макрос
Py_VA_COPYкопирует состояние списка аргументов переменной длины. Он эквивалентен va_copy из C99, но доступен на всех платформах Python (bpo-2443).Новая функция C API
PySys_SetArgvEx()позволяет встроенному интерпретатору устанавливатьsys.argvбез измененияsys.path(bpo-5753).PyEval_CallObjectтеперь доступен только в форме макроса. Объявление функции, которое сохранялось по причинам обратной совместимости, теперь удалено – макрос был введён в 1997 году (bpo-8276).Появилась новая функция
PyLong_AsLongLongAndOverflow(), которая аналогичнаPyLong_AsLongAndOverflow(). Обе служат для преобразования Pythonintв нативный тип фиксированной ширины, с обнаружением случаев, когда преобразование не помещается (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¶Porting to 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 следует использовать APIPyCapsule; новый тип имеет чётко определённый интерфейс для передачи информации о типобезопасности и менее сложную сигнатуру вызова деструктора.Функция
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 с промежуточными таблицами перевода соответствующего типа.(Предложено Georg Brandl; 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)
(Предложено Georg Brandl и Mattias Brändström; appspot issue 53094.)
struct.pack()теперь допускает только байты для кода упаковки строкs. Раньше он принимал текстовые аргументы и неявно кодировал их в байты через UTF-8. Это было проблематично, так как строило предположения о верной кодировке и потому что кодировка с переменной длиной может дать сбой при записи в сегмент структуры фиксированной длины.Код вида
struct.pack('<6sHHBBB', 'GIF87a', x, y)следует переписать с использованием байтов вместо текста:struct.pack('<6sHHBBB', b'GIF87a', x, y).(Обнаружено David Beazley, исправлено Victor Stinner; bpo-10783.)
Класс
xml.etree.ElementTreeтеперь вызываетxml.etree.ElementTree.ParseErrorпри неудачном разборе. Ранее вызывалосьxml.parsers.expat.ExpatError.Новое, более длинное значение
str()для чисел с плавающей точкой может нарушить doctest-тесты, которые полагаются на старый формат вывода.В
subprocess.Popenзначение по умолчанию для close_fds теперь равноTrueв Unix; в Windows оно равноTrue, если три стандартных потока установлены вNone, иFalseв противном случае. Раньше close_fds всегда былоFalseпо умолчанию, что приводило к трудноуловимым ошибкам или состояниям гонки, когда открытые файловые дескрипторы просачивались в дочерний процесс.Поддержка устаревшего HTTP 0.9 удалена из
urllib.requestиhttp.client. Такая поддержка по-прежнему присутствует на стороне сервера (вhttp.server).(Предложено Antoine Pitrou, 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().