Что нового в Python 3.2¶
- Автор
Раймонд Хеттингер
В этой статье рассказывается о новых возможностях в Python 3.2 по сравнению с 3.1. Python 3.2 был выпущен 20 февраля 2011 года. В статье уделено внимание нескольким основным моментам и приведено несколько примеров. Для получения более подробной информации смотрите файл Misc/NEWS.
См.также
PEP 392 - График выхода Python 3.2
PEP 384: Определение стабильного ABI¶
В прошлом модули расширения, созданные для одной версии Python, часто были непригодны для использования в других версиях Python. Особенно на Windows, каждый выпуск Python требовал перестройки всех модулей расширения, которые хотелось использовать. Это требование было результатом свободного доступа к внутренним компонентам интерпретатора Python, которые могли использовать модули расширения.
В Python 3.2 появился альтернативный подход: модули расширения, которые ограничивают себя ограниченным API (определяя Py_LIMITED_API), не могут использовать многие внутренние функции, но ограничены набором функций API, который обещает быть стабильным в течение нескольких релизов. Как следствие, модули расширения, созданные для 3.2 в этом режиме, будут работать и в 3.3, 3.4 и так далее. Модули расширения, использующие детали структур памяти, все еще могут быть собраны, но их необходимо будет перекомпилировать для каждого выпуска.
См.также
- PEP 384 - Определение стабильного ABI
PEP написан Мартином фон Лёвисом.
PEP 389: Модуль разбора командной строки Argparse¶
Новый модуль для разбора командной строки, argparse
, был введен для преодоления ограничений optparse
, который не обеспечивал поддержку позиционных аргументов (не только опций), подкоманд, требуемых опций и других распространенных моделей указания и проверки опций.
Этот модуль уже имел широкий успех в сообществе в качестве стороннего модуля. Будучи более полнофункциональным, чем его предшественник, модуль argparse
теперь является предпочтительным модулем для обработки командной строки. Более старый модуль все еще остается доступным из-за значительного количества унаследованного кода, который зависит от него.
Вот аннотированный пример парсера, демонстрирующий такие возможности, как ограничение результатов набором вариантов, указание метаварь на экране справки, проверка наличия одного или нескольких позиционных аргументов и создание обязательной опции:
import argparse
parser = argparse.ArgumentParser(
description = 'Manage servers', # main description for help
epilog = 'Tested on Solaris and Linux') # displayed after help
parser.add_argument('action', # argument name
choices = ['deploy', 'start', 'stop'], # three allowed values
help = 'action on each target') # help msg
parser.add_argument('targets',
metavar = 'HOSTNAME', # var name used in help msg
nargs = '+', # require one or more targets
help = 'url for target machines') # help msg explanation
parser.add_argument('-u', '--user', # -u or --user option
required = True, # make it a required argument
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') # first subgroup
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', # second subgroup
aliases=('steer', 'turn')) # equivalent names
parser_m.add_argument('-c', '--course', type=int, required=True)
parser_m.add_argument('-s', '--speed', type=int, default=0)
$ ./helm.py --help # top level help (launch and move)
$ ./helm.py launch --help # help for launch options
$ ./helm.py launch --missiles # set missiles=True and torpedos=False
$ ./helm.py steer --course 180 --speed 5 # set movement parameters
См.также
- PEP 389 - Новый модуль разбора командной строки
PEP написан Стивеном Бетардом.
Обновление кода optparse для получения подробной информации об отличиях от optparse
.
PEP 391: Конфигурация на основе словаря для ведения журнала¶
Модуль logging
предоставлял два вида конфигурации, один стиль с вызовами функций для каждой опции или другой стиль, управляемый внешним файлом, сохраненным в формате ConfigParser
. Эти варианты не обеспечивали гибкости при создании конфигураций из файлов JSON или YAML, а также не поддерживали инкрементную конфигурацию, которая необходима для указания параметров регистратора из командной строки.
Для поддержки более гибкого стиля модуль теперь предлагает logging.config.dictConfig()
для задания конфигурации протоколирования с помощью обычных словарей Python. Параметры конфигурации включают форматеры, обработчики, фильтры и регистраторы. Вот рабочий пример словаря конфигурации:
{"version": 1,
"formatters": {"brief": {"format": "%(levelname)-8s: %(name)-15s: %(message)s"},
"full": {"format": "%(asctime)s %(name)-15s %(levelname)-8s %(message)s"}
},
"handlers": {"console": {
"class": "logging.StreamHandler",
"formatter": "brief",
"level": "INFO",
"stream": "ext://sys.stdout"},
"console_priority": {
"class": "logging.StreamHandler",
"formatter": "full",
"level": "ERROR",
"stream": "ext://sys.stderr"}
},
"root": {"level": "DEBUG", "handlers": ["console", "console_priority"]}}
Если этот словарь хранится в файле с именем conf.json
, его можно загрузить и вызвать с помощью кода, подобного этому:
>>> import json, logging.config
>>> with open('conf.json') as f:
... conf = json.load(f)
...
>>> logging.config.dictConfig(conf)
>>> logging.info("Transaction completed normally")
INFO : root : Transaction completed normally
>>> logging.critical("Abnormal termination")
2011-02-17 11:14:36,694 root CRITICAL Abnormal termination
См.также
- PEP 391 - Конфигурация на основе словаря для ведения журнала
PEP написан Винаем Саджипом.
PEP 3148: Модуль concurrent.futures
¶
Код для создания и управления параллелизмом собирается в новом пространстве имен верхнего уровня, concurrent. Его первым членом является пакет futures, который предоставляет единый высокоуровневый интерфейс для управления потоками и процессами.
Дизайн concurrent.futures
был вдохновлен пакетом java.util.concurrent. В этой модели выполняющийся вызов и его результат представлены объектом Future
, который абстрагирует функции, общие для потоков, процессов и удаленных вызовов процедур. Этот объект поддерживает проверку состояния (запущен или выполнен), тайм-ауты, отмены, добавление обратных вызовов, а также доступ к результатам или исключениям.
Основным предложением нового модуля является пара классов исполнителей для запуска и управления вызовами. Цель исполнителей - упростить использование существующих инструментов для выполнения параллельных вызовов. Они экономят усилия, необходимые для создания пула ресурсов, запуска вызовов, создания очереди результатов, добавления обработки тайм-аута и ограничения общего числа потоков, процессов или удаленных вызовов процедур.
В идеале каждое приложение должно использовать один исполнитель для нескольких компонентов, чтобы можно было централизованно управлять лимитами процессов и потоков. Это решает проблему проектирования, возникающую, когда каждый компонент имеет свою собственную конкурирующую стратегию управления ресурсами.
Оба класса имеют общий интерфейс с тремя методами: submit()
для планирования вызываемого объекта и возврата объекта Future
; map()
для планирования многих асинхронных вызовов одновременно и shutdown()
для освобождения ресурсов. Класс является context manager и может быть использован в операторе with
для обеспечения автоматического освобождения ресурсов после завершения выполнения текущих ожидающих фьючерсов.
Простым примером ThreadPoolExecutor
является запуск четырех параллельных потоков для копирования файлов:
import concurrent.futures, shutil
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as e:
e.submit(shutil.copy, 'src1.txt', 'dest1.txt')
e.submit(shutil.copy, 'src2.txt', 'dest2.txt')
e.submit(shutil.copy, 'src3.txt', 'dest3.txt')
e.submit(shutil.copy, 'src3.txt', 'dest4.txt')
См.также
- PEP 3148 - Фьючерсы - выполнение вычислений асинхронно
PEP написан Брайаном Куинланом.
Code for Threaded Parallel URL reads, пример использования потоков для параллельной выборки нескольких веб-страниц.
Code for computing prime numbers in parallel, пример, демонстрирующий ProcessPoolExecutor
.
PEP 3147: Справочники репозиториев PYC¶
Схема Python для кэширования байткода в файлах .pyc не очень хорошо работала в средах с несколькими интерпретаторами Python. Если один интерпретатор сталкивался с кэшированным файлом, созданным другим интерпретатором, он перекомпилировал исходный текст и перезаписывал кэшированный файл, теряя таким образом преимущества кэширования.
Проблема «pyc-борьбы» становится все более актуальной, поскольку дистрибутивы Linux стали поставляться с несколькими версиями Python. Эти конфликты также возникают с альтернативами CPython, такими как Unladen Swallow.
Чтобы решить эту проблему, механизм импорта Python был расширен для использования отдельных имен файлов для каждого интерпретатора. Вместо того, чтобы Python 3.2, Python 3.3 и Unladen Swallow искали файл под названием «mymodule.pyc», теперь они будут искать «mymodule.cpython-32.pyc», «mymodule.cpython-33.pyc» и «mymodule.unladen10.pyc». А чтобы все эти новые файлы не загромождали каталоги исходников, файлы pyc теперь собираются в каталоге «__pycache__», хранящемся в каталоге пакета.
Помимо имен файлов и целевых каталогов, новая схема имеет несколько аспектов, которые видны программисту:
Импортируемые модули теперь имеют атрибут
__cached__
, который хранит имя фактического файла, который был импортирован:>>> import collections >>> collections.__cached__ 'c:/py32/lib/__pycache__/collections.cpython-32.pyc'
Метка, уникальная для каждого интерпретатора, доступна из модуля
imp
:>>> import imp >>> imp.get_tag() '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') 'c:/py32/lib/__pycache__/collections.cpython-32.pyc'
Модули
py_compile
иcompileall
были обновлены, чтобы отразить новое соглашение об именовании и целевой каталог. Вызов команды compileall из командной строки имеет новые опции:-i
для указания списка файлов и каталогов для компиляции и-b
, который заставляет записывать файлы байткода в их традиционное местоположение, а не в __pycache__.Модуль
importlib.abc
был обновлен новыми abstract base classes для загрузки файлов байткода. Устаревшие ABC,PyLoader
иPyPycLoader
, были упразднены (инструкции о том, как сохранить совместимость с Python 3.1, включены в документацию).
См.также
- PEP 3147 - Директории репозитория PYC
PEP написан Барри Варшавом.
PEP 3149: Версия ABI для файлов .so с метками¶
Каталог репозитория PYC позволяет совместно размещать несколько файлов кэша байткода. Этот PEP реализует аналогичный механизм для разделяемых объектных файлов, предоставляя им общий каталог и отдельные имена для каждой версии.
Общий каталог называется «pyshared», а имена файлов различаются по реализации Python (например, CPython, PyPy, Jython и т.д.), номерам мажорной и минорной версий и необязательным флагам сборки (например, «d» для debug, «m» для pymalloc, «u» для 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') # find the version tag
'cpython-32mu'
>>> sysconfig.get_config_var('EXT_SUFFIX') # find the full filename extension
'.cpython-32mu.so'
См.также
- PEP 3149 - Версия ABI, отмеченная в файлах .so
PEP написан Барри Варшавом.
PEP 3333: Интерфейс шлюза веб-сервера Python v1.0.1¶
Этот информационный PEP разъясняет, как вопросы байтов/текста должны обрабатываться протоколом WSGI. Проблема в том, что работа со строками в Python 3 удобнее всего осуществляется с помощью типа str
, хотя сам протокол HTTP ориентирован на байты.
PEP различает так называемые нативные строки, которые используются для заголовков запросов/ответов и метаданных, и байтовые строки, которые используются для тел запросов и ответов.
Родные строки* всегда имеют тип str
, но ограничены кодовыми точками от U+0000 до U+00FF, которые можно перевести в байты, используя кодировку Latin-1. Эти строки используются для ключей и значений в словаре окружения и для заголовков и статусов ответа в функции start_response()
. Они должны следовать за RFC 2616 в отношении кодировки. То есть, они должны быть либо ISO-8859-1 символами, либо использовать RFC 2047 кодировку MIME.
Для разработчиков, переносящих приложения WSGI с Python 2, вот основные моменты:
Если приложение уже использовало строки для заголовков в Python 2, никаких изменений не требуется.
Если вместо этого приложение кодировало выходные заголовки или декодировало входные заголовки, то заголовки нужно будет перекодировать в Latin-1. Например, выходной заголовок, закодированный в utf-8 с помощью
h.encode('utf-8')
, теперь нужно преобразовать из байтов в родные строки с помощьюh.encode('utf-8').decode('latin-1')
.Значения, выдаваемые приложением или отправляемые с помощью метода
write()
, должны быть байтовыми строками. Функцияstart_response()
и среда должны использовать родные строки. Смешивать эти два типа нельзя.
Для реализаторов серверов, пишущих пути CGI-to-WSGI или другие протоколы в стиле CGI, пользователи должны иметь возможность доступа к окружению с помощью родных строк, даже если базовая платформа может иметь другую конвенцию. Чтобы преодолеть этот разрыв, модуль wsgiref
имеет новую функцию wsgiref.handlers.read_environ()
для перекодирования CGI-переменных из os.environ
в родные строки и возврата нового словаря.
См.также
- PEP 3333 - Интерфейс шлюза веб-сервера Python v1.0.1
PEP написан Филиппом Эби.
Другие языковые изменения¶
Некоторые более мелкие изменения, внесенные в основной язык Python, следующие:
Форматирование строк для
format()
иstr.format()
получило новые возможности для символа формата #. Ранее для целых чисел в двоичной, восьмеричной или шестнадцатеричной системе счисления он вызывал префикс „0b“, „0o“ или „0x“ соответственно. Теперь он также может обрабатывать плавающие, комплексные и десятичные числа, заставляя вывод всегда иметь десятичную точку, даже если за ней нет цифр.>>> format(20, '#o') '0o24' >>> format(12.34, '#5.0f') ' 12.'
(Предложено Марком Дикинсоном и реализовано Эриком Смитом в bpo-7094).
Существует также новый метод
str.format_map()
, который расширяет возможности существующего методаstr.format()
, принимая произвольные объекты mapping. Этот новый метод позволяет использовать форматирование строк с любым из множества словареподобных объектов 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).
Интерпретатор теперь можно запускать с опцией quiet,
-q
, чтобы предотвратить отображение информации об авторских правах и версии в интерактивном режиме. Опция может быть проверена с помощью атрибутаsys.flags
:$ python -q >>> sys.flags sys.flags(debug=0, division_warning=0, inspect=0, interactive=0, optimize=0, dont_write_bytecode=0, no_user_site=0, no_site=0, ignore_environment=0, verbose=0, bytes_warning=0, quiet=1)
(Внесено Марцином Войдыром в bpo-1772833).
Функция
hasattr()
работает, вызываяgetattr()
и определяя, возникло ли исключение. Эта техника позволяет ей обнаруживать методы, созданные динамически с помощью__getattr__()
или__getattribute__()
, которые в противном случае отсутствовали бы в словаре класса. Раньше hasattr ловил любое исключение, возможно, маскируя настоящие ошибки. Теперь hasattr был ужесточен, чтобы перехватывать толькоAttributeError
и пропускать другие исключения:>>> class A: ... @property ... def f(self): ... return 1 // 0 ... >>> a = A() >>> hasattr(a, 'f') Traceback (most recent call last): ... ZeroDivisionError: integer division or modulo by zero
(Обнаружено Юрием Селивановым и исправлено Бенджамином Петерсоном; bpo-9666).
str()
плавающего или комплексного числа теперь совпадает с егоrepr()
. Ранее формаstr()
была короче, но это приводило к путанице и больше не нужно, так как по умолчанию отображается максимально короткоеrepr()
:>>> import math >>> repr(math.pi) '3.141592653589793' >>> str(math.pi) '3.141592653589793'
(Предложено и реализовано Марком Дикинсоном; bpo-9337).
Объекты
memoryview
теперь имеют методrelease()
, и они также теперь поддерживают протокол управления контекстом. Это позволяет своевременно освободить любые ресурсы, которые были получены при запросе буфера от исходного объекта.>>> with memoryview(b'abcdefgh') as v: ... print(v.tolist()) [97, 98, 99, 100, 101, 102, 103, 104]
(Добавлено Антуаном Питру; bpo-9757).
Ранее было незаконно удалять имя из локального пространства имен, если оно встречается как свободная переменная во вложенном блоке:
def outer(x): def inner(): return x inner() del x
Теперь это разрешено. Помните, что цель предложения
except
очищается, поэтому этот код, который работал в Python 2.6, поднялSyntaxError
в Python 3.1 и теперь снова работает:def f(): def print_error(): print(e) try: something except Exception as e: print_error() # implicit "del e" here
(См. bpo-4617.)
Внутренний инструмент
structsequence
теперь создает подклассы tuple. Это означает, что C-структуры, такие как структуры, возвращаемыеos.stat()
,time.gmtime()
иsys.version_info
, теперь работают как named tuple и теперь работают с функциями и методами, которые ожидают кортеж в качестве аргумента. Это большой шаг вперед на пути к тому, чтобы сделать структуры C такими же гибкими, как их аналоги в чистом Python:>>> import sys >>> isinstance(sys.version_info, tuple) True >>> 'Version %d.%d.%d %s(%d)' % sys.version_info 'Version 3.2.0 final(0)'
(Предложено Arfrever Frehtes Taifersar Arahesis и реализовано Бенджамином Петерсоном в bpo-8413).
Предупреждения теперь легче контролировать с помощью переменной окружения
PYTHONWARNINGS
в качестве альтернативы использованию-W
в командной строке:$ export PYTHONWARNINGS='ignore::RuntimeWarning::,once::UnicodeWarning::'
(Предложено Барри Варшавом и реализовано Филипом Дженви в bpo-7301).
Была добавлена новая категория предупреждений
ResourceWarning
. Она выдается при обнаружении потенциальных проблем с потреблением ресурсов или очисткой. По умолчанию она отключена в обычных сборках релиза, но может быть включена средствами, предоставляемыми модулемwarnings
, или в командной строке.При завершении работы интерпретатора выдается сообщение
ResourceWarning
, если списокgc.garbage
не пуст, а если установленgc.DEBUG_UNCOLLECTABLE
, то выводятся все не собираемые объекты. Это сделано для того, чтобы программист знал, что его код содержит проблемы с финализацией объектов.Ошибка
ResourceWarning
также выдается, когда объект file object уничтожается без явного закрытия. Хотя деаллокатор такого объекта гарантирует закрытие базового ресурса операционной системы (обычно дескриптора файла), задержка в деаллокации объекта может привести к различным проблемам, особенно под Windows. Вот пример включения предупреждения из командной строки:$ python -q -Wdefault >>> f = open("foo", "wb") >>> del f __main__:1: ResourceWarning: unclosed file <_io.BufferedWriter name='foo'>
(Добавлено Антуаном Питру и Георгом Брандлом в bpo-10093 и bpo-477863).
Объекты
range
теперь поддерживают методы index и count. Это часть усилий, направленных на то, чтобы больше объектов полностью реализовывалиcollections.Sequence
abstract base class. В результате язык будет иметь более единообразный API. Кроме того, объектыrange
теперь поддерживают нарезку и отрицательные индексы, даже при значениях больше, чемsys.maxsize
. Это делает range более совместимым со списками:>>> range(0, 100, 2).count(10) 1 >>> range(0, 100, 2).index(10) 5 >>> range(0, 100, 2)[5] 10 >>> range(0, 100, 2)[0:5] range(0, 10, 2)
(При участии Даниэля Штуцбаха в bpo-9213, Александра Белопольского в bpo-2690 и Ника Коглана в bpo-10889).
Встроенная функция
callable()
из Py2.x была воскрешена. Она предоставляет краткую, читабельную альтернативу использованию abstract base class в выражении типаisinstance(x, collections.Callable)
:>>> callable(max) True >>> callable(20) False
(См. bpo-10518.)
Механизм импорта Python теперь может загружать модули, установленные в каталогах, в имени пути к которым присутствуют символы, отличные от ASCII. Это позволило решить проблему с домашними каталогами для пользователей, у которых в имени пользователя присутствуют символы, отличные от ASCII.
(Требуется обширная работа Виктора Стиннера в bpo-9425).
Новые, улучшенные и устаревшие модули¶
Стандартная библиотека Python претерпела значительные усилия по обслуживанию и улучшению качества.
Самая большая новость для Python 3.2 заключается в том, что пакет email
, модуль mailbox
и модули nntplib
теперь корректно работают с моделью байт/текст в Python 3. Впервые реализована корректная обработка сообщений со смешанными кодировками.
Во всей стандартной библиотеке больше внимания уделяется кодировкам и вопросам соотношения текста и байтов. В частности, при взаимодействии с операционной системой теперь лучше обмениваться данными, отличными от ASCII, используя кодировку Windows MBCS, кодировки с учетом локальных особенностей или UTF-8.
Еще одним значительным выигрышем является добавление значительно лучшей поддержки SSL соединений и сертификатов безопасности.
Кроме того, теперь больше классов реализуют context manager для поддержки удобной и надежной очистки ресурсов с помощью оператора with
.
электронная почта¶
Удобство использования пакета email
в Python 3 было в основном исправлено благодаря активным усилиям Р. Дэвида Мюррея. Проблема заключалась в том, что электронные письма обычно читаются и хранятся в виде bytes
, а не str
текста, и они могут содержать несколько кодировок в пределах одного письма. Поэтому пакет email необходимо было расширить для разбора и генерации сообщений электронной почты в формате байтов.
Новые функции
message_from_bytes()
иmessage_from_binary_file()
, а также новые классыBytesFeedParser
иBytesParser
позволяют разбирать данные двоичных сообщений на объекты модели.Если в модель введены байты,
get_payload()
по умолчанию декодирует тело сообщения, имеющее Content-Transfer-Encoding в 8bit, используя charset, указанный в MIME-заголовках, и возвращает полученную строку.Учитывая входные байты в модель,
Generator
будет преобразовывать тела сообщений, которые имеют Content-Transfer-Encoding из 8 бит в 7 бит Content-Transfer-Encoding.Заголовки с некодированными байтами, не являющимися байтами ASCII, считаются RFC 2047- закодированными с использованием неизвестного-8-битного набора символов.
Новый класс
BytesGenerator
производит байты в качестве выходных данных, сохраняя все неизменные данные не в формате ASCII, которые присутствовали во входных данных, использованных для построения модели, включая тела сообщений с Content-Transfer-Encoding, равным 8bit.Класс
smtplib
SMTP
теперь принимает байтовую строку для аргумента msg методаsendmail()
, а новый методsend_message()
принимает объектMessage
и может по желанию получать адреса from_addr и to_addrs непосредственно из объекта.
(Предложено и реализовано Р. Дэвидом Мюрреем, bpo-4661 и bpo-10321).
дерево элементов¶
Пакет 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 на сайте Фредрика Лунда.
(При участии Флорана Ксиклуна и Фредрика Лунда, 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: ... get_phone_number(name) # cached lookup
Чтобы помочь в выборе эффективного размера кэша, функция wrapped оснащена инструментами для отслеживания статистики кэша:
>>> get_phone_number.cache_info() CacheInfo(hits=4805, misses=980, maxsize=300, currsize=300)
Если таблица телефонного списка обновляется, устаревшее содержимое кэша может быть очищено с помощью:
>>> get_phone_number.cache_clear()
(При участии Раймонда Хеттингера и с использованием идей дизайна Джима Бейкера, Мики Тебека и Ника Коглана; см. recipe 498245, recipe 577479, bpo-10586 и bpo-10593).
Декоратор
functools.wraps()
теперь добавляет атрибут__wrapped__
, указывающий на исходную вызываемую функцию. Это позволяет интроспективно исследовать обернутые функции. Он также копирует__annotations__
, если он определен. И теперь он также изящно пропускает недостающие атрибуты, такие как__doc__
, которые могут быть не определены для обернутой вызываемой функции.В приведенном выше примере кэш можно удалить, восстановив исходную функцию:
>>> get_phone_number = get_phone_number.__wrapped__ # uncached function
(Авторы Ник Коглан и Терренс Коул; bpo-9567, bpo-3445 и bpo-8814).
Чтобы помочь написать классы с богатыми методами сравнения, новый декоратор
functools.total_ordering()
будет использовать существующие методы равенства и неравенства для заполнения оставшихся методов.Например, ввод __eq__ и __lt__ позволит
total_ordering()
заполнить __le__, __gt__ и __ge__:@total_ordering class Student: def __eq__(self, other): return ((self.lastname.lower(), self.firstname.lower()) == (other.lastname.lower(), other.firstname.lower())) def __lt__(self, other): return ((self.lastname.lower(), self.firstname.lower()) < (other.lastname.lower(), other.firstname.lower()))
С декоратором total_ordering остальные методы сравнения заполняются автоматически.
(При участии Раймонда Хеттингера.)
Для облегчения переноса программ с Python 2 функция
functools.cmp_to_key()
преобразует функцию сравнения старого стиля в современную key function:>>> # locale-aware sort order >>> sorted(iterable, key=cmp_to_key(locale.strcoll))
Примеры сортировки и краткое руководство по сортировке см. в руководстве Sorting HowTo.
(При участии Раймонда Хеттингера.)
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)) # cumulative probability distribution [0.1, 0.5, 0.7, 1.0]
Пример использования
accumulate()
см. в examples for the random module.(При участии Раймонда Хеттингера и с учетом предложений Марка Дикинсона по дизайну).
коллекции¶
Класс
collections.Counter
теперь имеет две формы вычитания на месте: существующий оператор -= для saturating subtraction и новый методsubtract()
для обычного вычитания. Первый подходит для multisets, которые имеют только положительные отсчеты, а второй больше подходит для случаев использования, допускающих отрицательные отсчеты:>>> from collections import Counter >>> tally = Counter(dogs=5, cats=3) >>> tally -= Counter(dogs=2, cats=8) # saturating subtraction >>> tally Counter({'dogs': 3})
>>> tally = Counter(dogs=5, cats=3) >>> tally.subtract(dogs=2, cats=8) # regular subtraction >>> tally Counter({'dogs': 3, 'cats': -5})
(При участии Раймонда Хеттингера.)
Класс
collections.OrderedDict
имеет новый методmove_to_end()
, который принимает существующий ключ и перемещает его на первую или последнюю позицию в упорядоченной последовательности.По умолчанию элемент перемещается на последнюю позицию. Это эквивалентно обновлению записи с помощью
od[k] = od.pop(k)
.Быстрая операция перехода к концу полезна для повторного упорядочивания записей. Например, упорядоченный словарь можно использовать для отслеживания порядка доступа путем старения записей от самой старой к самой последней.
>>> from collections import OrderedDict >>> d = OrderedDict.fromkeys(['a', 'b', 'X', 'd', 'e']) >>> list(d) ['a', 'b', 'X', 'd', 'e'] >>> d.move_to_end('X') >>> list(d) ['a', 'b', 'd', 'e', 'X']
(При участии Раймонда Хеттингера.)
Класс
collections.deque
оброс двумя новыми методамиcount()
иreverse()
, которые делают их более заменяемыми для объектовlist
:>>> from collections import deque >>> d = deque('simsalabim') >>> d.count('s') 2 >>> d.reverse() >>> d deque(['m', 'i', 'b', 'a', 'l', 'a', 's', 'm', 'i', 's'])
(При участии Раймонда Хеттингера.)
нарезание резьбы¶
Модуль threading
содержит новый класс синхронизации Barrier
, позволяющий заставить несколько потоков ждать, пока все они не достигнут общей точки барьера. Барьеры полезны для обеспечения того, чтобы задача с несколькими предварительными условиями не выполнялась, пока не завершатся все предшествующие задачи.
Барьеры могут работать с произвольным числом потоков. Это обобщение Rendezvous, которое определяется только для двух потоков.
Реализованные в виде двухфазного циклического барьера, объекты Barrier
подходят для использования в циклах. Раздельные фазы заполнения и слива гарантируют, что все потоки будут освобождены (слиты) до того, как любой из них сможет вернуться в цикл и снова войти в барьер. Барьер полностью сбрасывается после каждого цикла.
Пример использования барьеров:
from threading import Barrier, Thread
def get_votes(site):
ballots = conduct_election(site)
all_polls_closed.wait() # do not count until all polls are closed
totals = summarize(ballots)
publish(site, totals)
all_polls_closed = Barrier(len(sites))
for site in sites:
Thread(target=get_votes, args=(site,)).start()
В данном примере барьер обеспечивает выполнение правила, согласно которому голоса не могут быть подсчитаны ни на одном избирательном участке до тех пор, пока все избирательные участки не будут закрыты. Обратите внимание, что решение с барьером похоже на решение с threading.Thread.join()
, но потоки остаются живыми и продолжают выполнять работу (подведение итогов голосования) после пересечения точки барьера.
Если какая-либо из задач-предшественниц может зависнуть или задержаться, может быть создан барьер с необязательным параметром timeout. Тогда, если период таймаута истекает до того, как все задачи-предшественники достигнут точки барьера, все ожидающие потоки освобождаются и возникает исключение BrokenBarrierError
:
def get_votes(site):
ballots = conduct_election(site)
try:
all_polls_closed.wait(timeout=midnight - time.now())
except BrokenBarrierError:
lockbox = seal_ballots(ballots)
queue.put(lockbox)
else:
totals = summarize(ballots)
publish(site, totals)
В этом примере барьер применяет более надежное правило. Если некоторые избирательные участки не заканчивают работу до полуночи, барьер отключается, бюллетени опечатываются и помещаются в очередь для последующей обработки.
Дополнительные примеры использования барьеров в параллельных вычислениях см. в Barrier Synchronization Patterns. Также простое, но подробное объяснение барьеров есть в The Little Book of Semaphores, раздел 3.6.
(Внесено Кристьяном Валуром Йонссоном, обзор API сделан Джеффри Ясскином в bpo-8777).
время и дата¶
В модуле
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, регулирующими формат%y
strptime.Начиная с Py3.2, использование эвристики угадывания века будет выдавать
DeprecationWarning
. Вместо этого рекомендуется установитьtime.accept2dyear
вFalse
, чтобы можно было использовать большие диапазоны дат без догадок:>>> import time, warnings >>> warnings.resetwarnings() # remove the default warning filters >>> time.accept2dyear = True # guess whether 11 means 11 or 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 # use the full range of allowable dates >>> time.asctime((11, 1, 1, 12, 34, 56, 4, 1, 0)) 'Fri Jan 1 12:34:56 11'
Некоторые функции теперь имеют значительно расширенные диапазоны дат. Когда
time.accept2dyear
равно false, функцияtime.asctime()
будет принимать любой год, который помещается в C int, а функцииtime.mktime()
иtime.strftime()
будут принимать полный диапазон, поддерживаемый соответствующими функциями операционной системы.
(Внесено Александром Белопольским и Виктором Стиннером в bpo-1289118, bpo-5094, bpo-6641, bpo-2706, bpo-1777412, bpo-8013 и bpo-10827).
математика¶
Модуль math
был обновлен шестью новыми функциями, вдохновленными стандартом C99.
Функция isfinite()
обеспечивает надежный и быстрый способ определения специальных значений. Она возвращает True
для обычных чисел и False
для Nan или Infinity:
>>> from math import isfinite
>>> [isfinite(x) for x in (123, 4.56, float('Nan'), float('Inf'))]
[True, True, False, False]
Функция expm1()
вычисляет e**x-1
для малых значений x без потери точности, которая обычно сопровождает вычитание почти равных величин:
>>> from math import expm1
>>> expm1(0.013671875) # more accurate way to compute e**x-1 for a small x
0.013765762467652909
Функция erf()
вычисляет интеграл вероятности или Gaussian error function. Дополнительная функция ошибки, erfc()
, является 1 - erf(x)
:
>>> from math import erf, erfc, sqrt
>>> erf(1.0/sqrt(2.0)) # portion of normal distribution within 1 standard deviation
0.682689492137086
>>> erfc(1.0/sqrt(2.0)) # portion of normal distribution outside 1 standard deviation
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) # six factorial
720.0
>>> lgamma(801.0) # log(800 factorial)
4551.950730698041
(При участии Марка Дикинсона.)
abc¶
Модуль abc
теперь поддерживает abstractclassmethod()
и abstractstaticmethod()
.
Эти инструменты позволяют определить abstract base class, который требует реализации определенного classmethod()
или staticmethod()
:
class Temperature(metaclass=abc.ABCMeta):
@abc.abstractclassmethod
def from_fahrenheit(cls, t):
...
@abc.abstractclassmethod
def from_celsius(cls, t):
...
(Патч предоставлен Даниэлем Урбаном; bpo-5867).
io¶
В io.BytesIO
появился новый метод getbuffer()
, который обеспечивает функциональность, аналогичную memoryview()
. Он создает редактируемое представление данных без создания копии. Произвольный доступ к буферу и поддержка нотации срезов хорошо подходят для редактирования на месте:
>>> REC_LEN, LOC_START, LOC_LEN = 34, 7, 11
>>> def change_location(buffer, record_number, location):
... start = record_number * REC_LEN + LOC_START
... buffer[start: start+LOC_LEN] = location
>>> import io
>>> byte_stream = io.BytesIO(
... b'G3805 storeroom Main chassis '
... b'X7899 shipping Reserve cog '
... b'L6988 receiving Primary sprocket'
... )
>>> buffer = byte_stream.getbuffer()
>>> change_location(buffer, 1, b'warehouse ')
>>> change_location(buffer, 0, b'showroom ')
>>> print(byte_stream.getvalue())
b'G3805 showroom Main chassis '
b'X7899 warehouse Reserve cog '
b'L6988 receiving Primary sprocket'
(Внесено Антуаном Питру из bpo-5506).
reprlib¶
При написании метода __repr__()
для пользовательского контейнера легко забыть обработать случай, когда член ссылается обратно на сам контейнер. Встроенные объекты Python, такие как list
и set
, обрабатывают самоссылку, отображая «…» в рекурсивной части строки представления.
Чтобы помочь в написании таких методов __repr__()
, модуль reprlib
имеет новый декоратор recursive_repr()
для обнаружения рекурсивных вызовов __repr__()
и подстановки вместо них строки-заполнителя:
>>> class MyList(list):
... @recursive_repr()
... def __repr__(self):
... return '<' + '|'.join(map(repr, self)) + '>'
...
>>> m = MyList('abc')
>>> m.append(m)
>>> m.append('x')
>>> print(m)
<'a'|'b'|'c'|...|'x'>
ведение журнала¶
В дополнение к описанной выше конфигурации на основе словаря, пакет logging
имеет множество других улучшений.
Документация по логированию была дополнена basic tutorial, advanced tutorialи cookbook рецептами логирования. Эти документы - самый быстрый способ узнать о протоколировании.
Функция установки 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
, который полезен для создания context manager, выполняющего двойную функцию декоратора функций.
В качестве удобства, эта новая функциональность используется contextmanager()
, чтобы не требовалось дополнительных усилий для поддержки обеих ролей.
Основная идея заключается в том, что и контекстные менеджеры, и декораторы функций могут быть использованы для обертки до и после выполнения действия. Контекстные менеджеры оборачивают группу утверждений с помощью оператора with
, а декораторы функций оборачивают группу утверждений, заключенных в функцию. Поэтому иногда возникает необходимость написать обертку для пред- или пост-действия, которую можно использовать в любой роли.
Например, иногда полезно обернуть функции или группы операторов регистратором, который может отслеживать время входа и время выхода. Вместо того чтобы писать декоратор функции и менеджер контекста для задачи, contextmanager()
предоставляет обе возможности в одном определении:
from contextlib import contextmanager
import logging
logging.basicConfig(level=logging.INFO)
@contextmanager
def track_entry_and_exit(name):
logging.info('Entering: %s', name)
yield
logging.info('Exiting: %s', name)
Раньше это можно было использовать только в качестве менеджера контекста:
with track_entry_and_exit('widget loader'):
print('Some time consuming activity goes here')
load_widget()
Теперь его можно использовать и как декоратор:
@track_entry_and_exit('widget loader')
def activity():
print('Some time consuming activity goes here')
load_widget()
Попытка выполнить две роли одновременно накладывает некоторые ограничения на технику. Контекстные менеджеры обычно имеют возможность возвращать аргумент, используемый оператором with
, но для декораторов функций параллели нет.
В приведенном выше примере нет чистого способа для контекстного менеджера track_entry_and_exit вернуть экземпляр журнала для использования в теле вложенных операторов.
(Внесено Майклом Фоордом из bpo-9110).
десятичные и дробные дроби¶
Марк Дикинсон разработал элегантную и эффективную схему, гарантирующую, что различные числовые типы данных будут иметь одинаковое хэш-значение, когда их фактические значения равны (bpo-8188):
assert hash(Fraction(3, 2)) == hash(1.5) == \
hash(Decimal("1.5")) == hash(complex(1.5, 0))
Некоторые детали хэширования раскрываются через новый атрибут sys.hash_info
, который описывает битовую ширину значения хэша, простой модуль, значения хэша для бесконечность и нан, а также множитель, используемый для мнимой части числа:
>>> sys.hash_info
sys.hash_info(width=64, modulus=2305843009213693951, inf=314159, nan=0, imag=1000003)
Раннее решение об ограничении совместимости различных числовых типов было смягчено. По-прежнему не поддерживается (и не рекомендуется) неявное смешивание в арифметических выражениях, таких как Decimal('1.1') + float('1.1')
, поскольку при этом теряется информация в процессе построения двоичного float. Однако, поскольку существующее значение с плавающей точкой может быть без потерь преобразовано в десятичное или рациональное представление, имеет смысл добавить их в конструктор и поддерживать сравнения смешанного типа.
Конструктор
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).
(При участии Марка Дикинсона и Раймонда Хеттингера).
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)
(При участии Тарека Зиаде и Джампаоло Родола в bpo-4972, и Георга Брандла в bpo-8046 и bpo-1286).
Класс FTP_TLS
теперь принимает параметр context, который представляет собой объект ssl.SSLContext
, позволяющий объединить параметры конфигурации SSL, сертификаты и закрытые ключи в единую (потенциально долгоживущую) структуру.
(Внесено Джампаоло Родола; bpo-8806).
popen¶
Функции os.popen()
и subprocess.Popen()
теперь поддерживают операторы with
для автоматического закрытия дескрипторов файлов.
(Вклад Антуана Питру и Брайана Куртина в bpo-7461 и bpo-10554).
выберите¶
Модуль select
теперь раскрывает новый постоянный атрибут PIPE_BUF
, который дает минимальное количество байтов, которые гарантированно не будут блокироваться, когда select.select()
говорит, что труба готова к записи.
>>> import select
>>> select.PIPE_BUF
512
(Доступно на Unix-системах. Исправление Себастьена Сабле в bpo-9862)
gzip и zipfile¶
gzip.GzipFile
теперь реализует io.BufferedIOBase
abstract base class (за исключением 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() # convert to utf-8
>>> len(b)
89
>>> c = gzip.compress(b)
>>> len(c)
77
>>> gzip.decompress(c).decode()[:42] # decompress and convert to text
'Three shall be the number thou shalt count'
(При участии Ананда Б. Пиллая в bpo-3488; и Антуана Питру, Нира Айдеса и Брайана Кертина в bpo-9962, bpo-1675951, bpo-7471 и bpo-2846).
Кроме того, класс zipfile.ZipExtFile
был переработан для представления файлов, хранящихся в архиве. Новая реализация значительно быстрее и может быть обернута в объект io.BufferedReader
для большего ускорения. Также решена проблема, когда чередующиеся вызовы read и readline давали неверные результаты.
(Патч предоставлен Ниром Эйдесом в bpo-7610).
tarfile¶
Класс TarFile
теперь можно использовать в качестве менеджера контекста. Кроме того, его метод add()
имеет новый параметр filter, который контролирует, какие файлы добавляются в архив, и позволяет редактировать метаданные файла.
Новый параметр filter заменяет старый, менее гибкий параметр exclude, который уже устарел. Если указан, необязательный параметр filter должен быть keyword argument. Пользовательская функция filter принимает объект TarInfo
и возвращает обновленный объект TarInfo
, или, если она хочет, чтобы файл был исключен, функция может вернуть None
:
>>> import tarfile, glob
>>> def myfilter(tarinfo):
... if tarinfo.isfile(): # only save real files
... tarinfo.uname = 'monty' # redact the user name
... return tarinfo
>>> with tarfile.open(name='myarchive.tar.gz', mode='w:gz') as tf:
... for filename in glob.glob('*.txt'):
... tf.add(filename, filter=myfilter)
... tf.list()
-rw-r--r-- monty/501 902 2011-01-26 17:59:11 annotations.txt
-rw-r--r-- monty/501 123 2011-01-26 17:59:11 general_questions.txt
-rw-r--r-- monty/501 3514 2011-01-26 17:59:11 prion.txt
-rw-r--r-- monty/501 124 2011-01-26 17:59:11 py_todo.txt
-rw-r--r-- monty/501 1399 2011-01-26 17:59:11 semaphore_notes.txt
(Предложено Тареком Зиаде и реализовано Ларсом Густебелем в bpo-6856).
hashlib¶
Модуль hashlib
имеет два новых константных атрибута, перечисляющих алгоритмы хэширования, гарантированно присутствующие во всех реализациях и доступные в текущей реализации:
>>> import hashlib
>>> hashlib.algorithms_guaranteed
{'sha1', 'sha224', 'sha384', 'sha256', 'sha512', 'md5'}
>>> hashlib.algorithms_available
{'md2', 'SHA256', 'SHA512', 'dsaWithSHA', 'mdc2', 'SHA224', 'MD4', 'sha256',
'sha512', 'ripemd160', 'SHA1', 'MDC2', 'SHA', 'SHA384', 'MD2',
'ecdsa-with-SHA1','md4', 'md5', 'sha1', 'DSA-SHA', 'sha224',
'dsaEncryption', 'DSA', 'RIPEMD160', 'sha', 'MD5', 'sha384'}
(Предложено Карлом Чене в bpo-7418).
ast¶
Модуль ast
представляет собой замечательный инструмент общего назначения для безопасной оценки строк выражений с использованием синтаксиса литералов Python. Функция ast.literal_eval()
служит безопасной альтернативой встроенной функции eval()
, которой легко злоупотреблять. Python 3.2 добавляет литералы bytes
и set
к списку поддерживаемых типов: строки, байты, числа, кортежи, списки, дикты, множества, булевы и None
.
>>> from ast import literal_eval
>>> request = "{'req': 3, 'func': 'pow', 'args': (2, 0.5)}"
>>> literal_eval(request)
{'args': (2, 0.5), 'req': 3, 'func': 'pow'}
>>> request = "os.system('do something harmful')"
>>> literal_eval(request)
Traceback (most recent call last):
...
ValueError: malformed node or string: <_ast.Call object at 0x101739a10>
(Реализовано Бенджамином Петерсоном и Георгом Брандлом.)
os¶
Различные операционные системы используют различные кодировки для имен файлов и переменных окружения. Модуль os
предоставляет две новые функции, fsencode()
и fsdecode()
, для кодирования и декодирования имен файлов:
>>> import os
>>> filename = 'Sehenswürdigkeiten'
>>> os.fsencode(filename)
b'Sehensw\xc3\xbcrdigkeiten'
Некоторые операционные системы разрешают прямой доступ к закодированным байтам в среде. Если это так, то константа os.supports_bytes_environ
будет истиной.
Для прямого доступа к закодированным переменным окружения (если они доступны), используйте новую функцию os.getenvb()
или используйте os.environb
, которая является байтовой версией os.environ
.
(При участии Виктора Стиннера.)
shutil¶
Функция shutil.copytree()
имеет две новые опции:
ignore_dangling_symlinks: когда
symlinks=False
, чтобы функция копировала файл, на который указывает симлинк, а не сам симлинк. Эта опция заглушает ошибку, возникающую, если файл не существует.copy_function: является вызываемой функцией, которая будет использоваться для копирования файлов. По умолчанию используется
shutil.copy2()
.
(При участии Тарека Зиаде.)
Кроме того, модуль shutil
теперь поддерживает archiving operations для zip-файлов, несжатых tar-файлов, gzipped tar-файлов и bzipped tar-файлов. Также есть функции для регистрации дополнительных форматов архивных файлов (таких как xz сжатые tarfiles или пользовательские форматы).
Основными функциями являются make_archive()
и unpack_archive()
. По умолчанию обе работают с текущим каталогом (который может быть задан командой os.chdir()
) и с любыми подкаталогами. Имя архивного файла должно быть указано полным именем пути. Этап архивирования является неразрушающим (исходные файлы остаются без изменений).
>>> import shutil, pprint
>>> os.chdir('mydata') # change to the source directory
>>> f = shutil.make_archive('/var/backup/mydata',
... 'zip') # archive the current directory
>>> f # show the name of archive
'/var/backup/mydata.zip'
>>> os.chdir('tmp') # change to an unpacking
>>> shutil.unpack_archive('/var/backup/mydata.zip') # recover the data
>>> pprint.pprint(shutil.get_archive_formats()) # display known formats
[('bztar', "bzip2'ed tar-file"),
('gztar', "gzip'ed tar-file"),
('tar', 'uncompressed tar file'),
('zip', 'ZIP file')]
>>> shutil.register_archive_format( # register a new archive format
... name='xz',
... function=xz.compress, # callable archiving function
... extra_args=[('level', 8)], # arguments to the function
... description='xz compression'
... )
(При участии Тарека Зиаде.)
sqlite3¶
Модуль sqlite3
был обновлен до версии pysqlite 2.6.0. В нем появились две новые возможности.
Атрибут
sqlite3.Connection.in_transit
является истинным, если существует активная транзакция для незафиксированных изменений.Методы
sqlite3.Connection.enable_load_extension()
иsqlite3.Connection.load_extension()
позволяют загружать расширения SQLite из файлов «.so». Одним из известных расширений является расширение полнотекстового поиска, распространяемое вместе с SQLite.
(При участии Р. Дэвида Мюррея и Шашвата Ананда; bpo-8845).
html¶
Был введен новый модуль html
с единственной функцией escape()
, которая используется для экранирования зарезервированных символов из HTML-разметки:
>>> import html
>>> html.escape('x > 2 && x < 7')
'x > 2 && x < 7'
розетка¶
Модуль socket
имеет два новых усовершенствования.
Объекты Socket теперь имеют метод
detach()
, который переводит сокет в закрытое состояние без фактического закрытия базового дескриптора файла. Последний затем может быть повторно использован для других целей. (Добавлено Антуаном Питру; bpo-8524).socket.create_connection()
теперь поддерживает протокол управления контекстом для безусловного потребления исключенийsocket.error
и закрытия сокета после завершения работы. (Внесено Джампаоло Родола; bpo-9794).
ssl¶
Модуль ssl
добавил ряд функций для удовлетворения общих требований к безопасным (зашифрованным, аутентифицированным) интернет-соединениям:
Новый класс
SSLContext
служит контейнером для постоянных данных SSL, таких как настройки протокола, сертификаты, закрытые ключи и различные другие параметры. Он включаетwrap_socket()
для создания SSL-сокета из SSL-контекста.Новая функция,
ssl.match_hostname()
, поддерживает проверку идентичности сервера для протоколов более высокого уровня, реализуя правила HTTPS (из RFC 2818), которые также подходят для других протоколов.Функция конструктора
ssl.wrap_socket()
теперь принимает аргумент ciphers. В строке ciphers перечислены допустимые алгоритмы шифрования в формате, описанном в OpenSSL documentation.При использовании последних версий 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).
сертификаты¶
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-соединение.
В HTTPSConnection
была добавлена поддержка проверки сертификатов и виртуальных хостов HTTPS.
Метод request()
на объектах соединения допускал необязательный аргумент body, чтобы file object можно было использовать для передачи содержимого запроса. Удобно, что аргумент body теперь также принимает объект iterable, если он включает явный заголовок Content-Length
. Этот расширенный интерфейс гораздо более гибкий, чем раньше.
Для установления HTTPS-соединения через прокси-сервер существует новый метод set_tunnel()
, который устанавливает хост и порт для туннелирования HTTP Connect.
Чтобы соответствовать поведению http.server
, клиентская библиотека HTTP теперь также кодирует заголовки в кодировке ISO-8859-1 (Latin-1). Она уже делала это для входящих заголовков, так что теперь поведение согласовано как для входящего, так и для исходящего трафика. (См. работу Армина Ронахера в bpo-10980).
unittest¶
Модуль unittest имеет ряд улучшений, поддерживающих обнаружение тестов для пакетов, более легкое экспериментирование в интерактивной подсказке, новые методы тесткейсов, улучшенные диагностические сообщения о неудачах тестов и более удобные имена методов.
Вызов командной строки
python -m unittest
теперь может принимать пути к файлам вместо имен модулей для запуска определенных тестов (bpo-10620). Новое обнаружение тестов может находить тесты внутри пакетов, обнаруживая любой тест, импортируемый из каталога верхнего уровня. Каталог верхнего уровня может быть указан с помощью опции -t, шаблон для поиска файлов с помощью-p
, а каталог для начала обнаружения с помощью-s
:$ python -m unittest discover -s my_proj_dir -p _test.py
(При участии Майкла Фоорда.)
Экспериментировать в интерактивной подсказке стало проще, поскольку класс
unittest.case.TestCase
теперь можно инстанцировать без аргументов:>>> from unittest import TestCase >>> TestCase().assertEqual(pow(2, 3), 8)
(При участии Майкла Фоорда.)
Модуль
unittest
имеет два новых метода,assertWarns()
иassertWarnsRegex()
для проверки того, что данный тип предупреждения вызван тестируемым кодом:with self.assertWarns(DeprecationWarning): legacy_function('XYZ')
(Внесено Антуаном Питру, bpo-9754).
Еще один новый метод,
assertCountEqual()
, используется для сравнения двух итераций, чтобы определить, равны ли их количества элементов (присутствуют ли одинаковые элементы с одинаковым количеством вхождений независимо от порядка):def test_anagram(self): self.assertCountEqual('algorithm', 'logarithm')
(При участии Раймонда Хеттингера.)
Главной особенностью модуля unittest является попытка выдать содержательную диагностику при неудачном выполнении теста. Когда это возможно, сбой записывается вместе с диф. выводом. Это особенно полезно для анализа журнальных файлов неудачных запусков тестов. Однако, поскольку диффы иногда могут быть объемными, появился новый атрибут
maxDiff
, задающий максимальную длину отображаемых диффов.Кроме того, имена методов в модуле подверглись некоторой чистке.
Например,
assertRegex()
- это новое название дляassertRegexpMatches()
, который был назван неправильно, потому что в тесте используетсяre.search()
, а неre.match()
. Другие методы, использующие регулярные выражения, теперь называются сокращенно «Regex», а не «Regexp» - это соответствует именам, используемым в других реализациях unittest, соответствует старому названию модуля Pythonre
, и имеет однозначный верблюжий регистр.(Внесено Раймондом Хеттингером и реализовано Эцио Мелотти).
Для улучшения согласованности некоторые давно используемые псевдонимы методов отменяются в пользу предпочтительных имен:
Старое имя
Предпочитаемое имя
assert_()
assertEquals()
assertNotEquals()
assertAlmostEquals()
assertNotAlmostEquals()
Аналогично, методы
TestCase.fail*
, устаревшие в Python 3.1, как ожидается, будут удалены в Python 3.3. Также смотрите раздел Утратившие актуальность псевдонимы в документацииunittest
.(Внесено Эцио Мелотти; bpo-9424).
Метод
assertDictContainsSubset()
был устаревшим, потому что он был неправильно реализован с аргументами в неправильном порядке. Это создавало трудноотлаживаемые оптические иллюзии, при которых тесты типаTestCase().assertDictContainsSubset({'a':1, 'b':2}, {'a':1})
проваливались.(При участии Раймонда Хеттингера.)
случайный¶
Целочисленные методы в модуле random
теперь лучше справляются с получением равномерных распределений. Ранее они вычисляли выборки с помощью int(n*random())
, который имел небольшое смещение всякий раз, когда n не являлось степенью двойки. Теперь множественные выборки производятся из диапазона до следующей степени двойки, и выборка сохраняется только тогда, когда она попадает в диапазон 0 <= x < n
. Затронуты функции и методы randrange()
, randint()
, choice()
, shuffle()
и sample()
.
(Внесено Раймондом Хеттингером; bpo-9025).
poplib¶
Класс POP3_SSL
теперь принимает параметр context, который представляет собой объект ssl.SSLContext
, позволяющий объединить параметры конфигурации SSL, сертификаты и закрытые ключи в единую (потенциально долгоживущую) структуру.
(Внесено Джампаоло Родола; bpo-8807).
asyncore¶
asyncore.dispatcher
теперь предоставляет метод handle_accepted()
, возвращающий пару (sock, addr), который вызывается, когда соединение действительно было установлено с новой удаленной конечной точкой. Предполагается, что он будет использоваться в качестве замены старого handle_accept()
и избавит пользователя от необходимости напрямую вызывать accept()
.
(Внесено Джампаоло Родола; bpo-6706).
tempfile¶
Модуль tempfile
имеет новый менеджер контекста TemporaryDirectory
, который обеспечивает легкую детерминированную очистку временных каталогов:
with tempfile.TemporaryDirectory() as tmpdirname:
print('created temporary dir:', tmpdirname)
(При участии Нила Шеменауэра и Ника Коглана; bpo-5178).
проверять¶
В модуле
inspect
появилась новая функцияgetgeneratorstate()
, позволяющая легко определить текущее состояние генератора-итератора:>>> from inspect import getgeneratorstate >>> def gen(): ... yield 'demo' >>> g = gen() >>> getgeneratorstate(g) 'GEN_CREATED' >>> next(g) 'demo' >>> getgeneratorstate(g) 'GEN_SUSPENDED' >>> next(g, None) >>> getgeneratorstate(g) 'GEN_CLOSED'
(При участии Родольфо Экхардта и Ника Коглана, bpo-10220).
Для поддержки поиска без возможности активации динамического атрибута в модуле
inspect
появилась новая функцияgetattr_static()
. В отличие отhasattr()
, это настоящий поиск только для чтения, который гарантированно не изменит состояние во время поиска:>>> class A: ... @property ... def f(self): ... print('Running') ... return 10 ... >>> a = A() >>> getattr(a, 'f') Running 10 >>> inspect.getattr_static(a, 'f') <property object at 0x1022bd788>
(При участии Майкла Фоорда.)
pydoc¶
Модуль pydoc
теперь предоставляет значительно улучшенный интерфейс веб-сервера, а также новую опцию командной строки -b
для автоматического открытия окна браузера для отображения этого сервера:
$ pydoc3.2 -b
(Внесено Роном Адамом; bpo-2001).
dis¶
В модуле dis
появились две новые функции для проверки кода, code_info()
и show_code()
. Обе предоставляют подробную информацию об объекте кода для заданной функции, метода, строки исходного кода или объекта кода. Первая возвращает строку, а вторая печатает ее:
>>> import dis, random
>>> dis.show_code(random.choice)
Name: choice
Filename: /Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/random.py
Argument count: 2
Kw-only arguments: 0
Number of locals: 3
Stack size: 11
Flags: OPTIMIZED, NEWLOCALS, NOFREE
Constants:
0: 'Choose a random element from a non-empty sequence.'
1: 'Cannot choose from an empty sequence'
Names:
0: _randbelow
1: len
2: ValueError
3: IndexError
Variable names:
0: self
1: seq
2: i
Кроме того, функция dis()
теперь принимает строковые аргументы, так что распространенная идиома dis(compile(s, '', 'eval'))
может быть сокращена до dis(s)
:
>>> dis('3*x+1 if x%2==1 else x//2')
1 0 LOAD_NAME 0 (x)
3 LOAD_CONST 0 (2)
6 BINARY_MODULO
7 LOAD_CONST 1 (1)
10 COMPARE_OP 2 (==)
13 POP_JUMP_IF_FALSE 28
16 LOAD_CONST 2 (3)
19 LOAD_NAME 0 (x)
22 BINARY_MULTIPLY
23 LOAD_CONST 1 (1)
26 BINARY_ADD
27 RETURN_VALUE
>> 28 LOAD_NAME 0 (x)
31 LOAD_CONST 0 (2)
34 BINARY_FLOOR_DIVIDE
35 RETURN_VALUE
Вместе взятые, эти улучшения облегчают изучение того, как реализован CPython, и позволяют увидеть своими глазами, что делает синтаксис языка «под землей».
(Внесено Ником Когланом из bpo-9147).
dbm¶
Все модули баз данных теперь поддерживают методы get()
и setdefault()
.
(Предложено Рэем Алленом в bpo-9523).
ctypes¶
Новый тип ctypes.c_ssize_t
представляет тип данных C ssize_t
.
сайт¶
Модуль site
содержит три новые функции, полезные для составления отчетов о деталях данной установки Python.
getsitepackages()
перечисляет все глобальные каталоги site-packages.getuserbase()
сообщает о базовом каталоге пользователя, в котором могут храниться данные.getusersitepackages()
раскрывает путь к директории site-packages для конкретного пользователя.
>>> import site
>>> site.getsitepackages()
['/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/site-packages',
'/Library/Frameworks/Python.framework/Versions/3.2/lib/site-python',
'/Library/Python/3.2/site-packages']
>>> site.getuserbase()
'/Users/raymondhettinger/Library/Python/3.2'
>>> site.getusersitepackages()
'/Users/raymondhettinger/Library/Python/3.2/lib/python/site-packages'
Удобно, что некоторые функции сайта доступны непосредственно из командной строки:
$ python -m site --user-base
/Users/raymondhettinger/.local
$ python -m site --user-site
/Users/raymondhettinger/.local/lib/python3.2/site-packages
(Внесено Тареком Зиаде в bpo-6693).
sysconfig¶
Новый модуль sysconfig
позволяет легко обнаружить пути установки и переменные конфигурации, которые различаются на разных платформах и установках.
Модуль предлагает функции простого доступа к информации о платформе и версии:
get_platform()
возвращает значения типа linux-i586 или macosx-10.6-ppc.get_python_version()
возвращает строку версии Python, например, «3.2».
Он также предоставляет доступ к путям и переменным, соответствующим одной из семи именованных схем, используемых distutils
. К ним относятся posix_prefix, posix_home, posix_user, nt, nt_user, os2, os2_home:
get_paths()
создает словарь, содержащий пути установки для текущей схемы установки.get_config_vars()
возвращает словарь переменных, специфичных для платформы.
Также имеется удобный интерфейс командной строки:
C:\Python32>python -m sysconfig
Platform: "win32"
Python version: "3.2"
Current installation scheme: "nt"
Paths:
data = "C:\Python32"
include = "C:\Python32\Include"
platinclude = "C:\Python32\Include"
platlib = "C:\Python32\Lib\site-packages"
platstdlib = "C:\Python32\Lib"
purelib = "C:\Python32\Lib\site-packages"
scripts = "C:\Python32\Scripts"
stdlib = "C:\Python32\Lib"
Variables:
BINDIR = "C:\Python32"
BINLIBDEST = "C:\Python32\Lib"
EXE = ".exe"
INCLUDEPY = "C:\Python32\Include"
LIBDEST = "C:\Python32\Lib"
SO = ".pyd"
VERSION = "32"
abiflags = ""
base = "C:\Python32"
exec_prefix = "C:\Python32"
platbase = "C:\Python32"
prefix = "C:\Python32"
projectbase = "C:\Python32"
py_version = "3.2"
py_version_nodot = "32"
py_version_short = "3.2"
srcdir = "C:\Python32"
userbase = "C:\Documents and Settings\Raymond\Application Data\Python"
(Перемещено из Distutils Тареком Зиаде).
pdb¶
Модуль отладчика pdb
получил ряд улучшений в удобстве использования:
pdb.py
теперь имеет опцию-c
, которая выполняет команды, заданные в файле сценария.pdbrc
.Файл сценария
.pdbrc
может содержать командыcontinue
иnext
, которые продолжают отладку.Конструктор класса
Pdb
теперь принимает аргумент nosigint.Новые команды:
l(list)
,ll(long list)
иsource
для листинга исходного кода.Новые команды:
display
иundisplay
для показа или скрытия значения выражения, если оно изменилось.Новая команда:
interact
для запуска интерактивного интерпретатора, содержащего глобальные и локальные имена, найденные в текущей области видимости.Точки останова могут быть очищены по номеру точки останова.
(При участии Георга Брандла, Антонио Куни и Ильи Сандлера).
configparser¶
Модуль configparser
был изменен для улучшения удобства использования и предсказуемости парсера по умолчанию и поддерживаемого им синтаксиса INI. Старый класс ConfigParser
был удален в пользу SafeConfigParser
, который в свою очередь был переименован в ConfigParser
. Поддержка встроенных комментариев теперь отключена по умолчанию, а дублирование секций и опций в одном источнике конфигурации не допускается.
Парсеры конфигурации получили новый API, основанный на протоколе сопоставления:
>>> parser = ConfigParser()
>>> parser.read_string("""
... [DEFAULT]
... location = upper left
... visible = yes
... editable = no
... color = blue
...
... [main]
... title = Main Menu
... color = green
...
... [options]
... title = Options
... """)
>>> parser['main']['color']
'green'
>>> parser['main']['editable']
'no'
>>> section = parser['options']
>>> section['title']
'Options'
>>> section['title'] = 'Options (editable: %(editable)s)'
>>> section['title']
'Options (editable: no)'
Новый API реализован поверх классического API, поэтому пользовательские подклассы парсеров должны иметь возможность использовать его без изменений.
Структура INI-файла, принимаемая парсерами конфигурации, теперь может быть настроена. Пользователи могут указать альтернативные разделители опций/значений и префиксы комментариев, изменить имя секции DEFAULT или переключить синтаксис интерполяции.
Имеется поддержка подключаемой интерполяции, включая дополнительный обработчик интерполяции ExtendedInterpolation
:
>>> parser = ConfigParser(interpolation=ExtendedInterpolation())
>>> parser.read_dict({'buildout': {'directory': '/home/ambv/zope9'},
... 'custom': {'prefix': '/usr/local'}})
>>> parser.read_string("""
... [buildout]
... parts =
... zope9
... instance
... find-links =
... ${buildout:directory}/downloads/dist
...
... [zope9]
... recipe = plone.recipe.zope9install
... location = /opt/zope
...
... [instance]
... recipe = plone.recipe.zope9instance
... zope9-location = ${zope9:location}
... zope-conf = ${custom:prefix}/etc/zope.conf
... """)
>>> parser['buildout']['find-links']
'\n/home/ambv/zope9/downloads/dist'
>>> parser['instance']['zope-conf']
'/usr/local/etc/zope.conf'
>>> instance = parser['instance']
>>> instance['zope-conf']
'/usr/local/etc/zope.conf'
>>> instance['zope9-location']
'/opt/zope'
Также был представлен ряд более мелких возможностей, таких как поддержка указания кодировки в операциях чтения, указание запасных значений для функций get, или чтение непосредственно из словарей и строк.
(Все изменения внесены Лукашем Ланга).
urllib.parse¶
Для модуля urllib.parse
был сделан ряд улучшений в плане удобства использования.
Функция urlparse()
теперь поддерживает адреса IPv6, как описано в RFC 2732:
>>> import urllib.parse
>>> urllib.parse.urlparse('http://[dead:beef:cafe:5417:affe:8FA3:deaf:feed]/foo/')
ParseResult(scheme='http',
netloc='[dead:beef:cafe:5417:affe:8FA3:deaf:feed]',
path='/foo/',
params='',
query='',
fragment='')
Функция urldefrag()
теперь возвращает named tuple:
>>> r = urllib.parse.urldefrag('http://python.org/about/#target')
>>> r
DefragResult(url='http://python.org/about/', fragment='target')
>>> r[0]
'http://python.org/about/'
>>> r.fragment
'target'
Кроме того, функция urlencode()
стала более гибкой, принимая в качестве аргумента query либо строку, либо тип байта. Если это строка, то параметры safe, encoding и error передаются в quote_plus()
для кодирования:
>>> urllib.parse.urlencode([
... ('type', 'telenovela'),
... ('name', '¿Dónde Está Elisa?')],
... encoding='latin-1')
'type=telenovela&name=%BFD%F3nde+Est%E1+Elisa%3F'
Как подробно описано в Разбор байтов в кодировке ASCII, все функции urllib.parse
теперь принимают на вход байтовые строки в ASCII-кодировке, если они не смешаны с обычными строками. Если в качестве параметров передаются байтовые строки в ASCII-кодировке, возвращаемые типы также будут байтовыми строками в ASCII-кодировке:
>>> urllib.parse.urlparse(b'http://www.python.org:80/about/')
ParseResultBytes(scheme=b'http', netloc=b'www.python.org:80',
path=b'/about/', params=b'', query=b'', fragment=b'')
(Работы Ника Коглана, Дэна Мана и Сентхила Кумарана в bpo-2987, bpo-5468 и bpo-9873).
почтовый ящик¶
Благодаря совместным усилиям Р. Дэвида Мюррея, модуль mailbox
был исправлен для Python 3.2. Проблема заключалась в том, что почтовый ящик изначально был разработан с текстовым интерфейсом, но сообщения электронной почты лучше всего представлять с помощью bytes
, поскольку различные части сообщения могут иметь разные кодировки.
Решение использовало бинарную поддержку пакета email
для разбора произвольных сообщений электронной почты. Кроме того, решение потребовало внесения ряда изменений в API.
Как и ожидалось, метод add()
для объектов mailbox.Mailbox
теперь принимает двоичный вход.
StringIO
и ввод из текстового файла устарели. Кроме того, ввод строк будет завершаться неудачей, если используются символы, отличные от ASCII. Ранее это происходило, когда письмо обрабатывалось на более позднем этапе.
Также появилась поддержка двоичного вывода. Метод get_file()
теперь возвращает файл в двоичном режиме (раньше он ошибочно устанавливал файл в текстовый режим). Также есть новый метод get_bytes()
, который возвращает bytes
представление сообщения, соответствующего заданному ключу.
Все еще можно получить недвоичный вывод, используя метод get_string()
старого API, но этот подход не очень полезен. Вместо этого лучше всего извлекать сообщения из объекта Message
или загружать их из двоичного ввода.
(Внесено Р. Дэвидом Мюрреем при участии Штеффена Даоде Нурпмесо и первоначального исправления Виктора Стиннера в bpo-9124).
turtledemo¶
Демонстрационный код для модуля turtle
был перемещен из каталога Demo в основную библиотеку. Он включает более дюжины примеров скриптов с живым отображением. Находясь на sys.path
, он теперь может быть запущен непосредственно из командной строки:
$ python -m turtledemo
(Перемещено из каталога Demo Александром Белопольским в bpo-10199).
Многопоточность¶
Механизм сериализации выполнения параллельно запущенных потоков Python (известный как GIL или глобальная блокировка интерпретатора) был переписан. Среди целей были более предсказуемые интервалы переключения и снижение накладных расходов, связанных с борьбой за блокировку и количеством последующих системных вызовов. Понятие «контрольный интервал» для разрешения переключения потоков было отменено и заменено абсолютной длительностью, выраженной в секундах. Этот параметр настраивается с помощью
sys.setswitchinterval()
. В настоящее время по умолчанию он равен 5 миллисекундам.Дополнительные подробности о реализации можно прочитать из сообщения python-dev mailing-list message (однако, «приоритетные запросы», раскрытые в этом сообщении, не были сохранены для включения).
(При участии Антуана Питру.)
Регулярные и рекурсивные блокировки теперь принимают необязательный аргумент timeout для своего метода
acquire()
. (Внесено Антуаном Питру; bpo-7316).Аналогично,
threading.Semaphore.acquire()
также получил аргумент timeout. (Внесено Торстеном Ландшоффом; bpo-850728).Регулярное и рекурсивное получение блокировок теперь может быть прервано сигналами на платформах, использующих Pthreads. Это означает, что Python-программы, зашедшие в тупик при получении блокировок, могут быть успешно завершены путем многократной отправки SIGINT процессу (нажатием клавиши Ctrl+C в большинстве оболочек). (Внесено Ридом Клекнером; bpo-8844).
Оптимизации¶
Добавлен ряд небольших улучшений производительности:
Оптимизатор Python теперь распознает шаблоны типа
x in {1, 2, 3}
как тест на принадлежность к набору констант. Оптимизатор преобразуетset
вfrozenset
и сохраняет предварительно созданную константу.Теперь, когда штраф за скорость устранен, можно начать писать тесты членства, используя set-notation. Этот стиль является одновременно семантически ясным и оперативно быстрым:
extension = name.rpartition('.')[2] if extension in {'xml', 'html', 'xhtml', 'css'}: handle(name)
(Патч и дополнительные тесты предоставлены Дейвом Малкольмом; bpo-6690).
Сериализация и несериализация данных с помощью модуля
pickle
теперь выполняется в несколько раз быстрее.(При участии Александра Вассалотти, Антуана Питру и команды Unladen Swallow в bpo-9410 и bpo-3873).
Timsort algorithm, используемый в
list.sort()
иsorted()
, теперь работает быстрее и использует меньше памяти при вызове с key function. Раньше каждый элемент списка обертывался временным объектом, который запоминал значение ключа, связанное с каждым элементом. Теперь два массива ключей и значений сортируются параллельно. Это экономит память, занимаемую обертками сортировки, и время, потерянное на делегирование сравнений.(Патч, созданный Даниэлем Штуцбахом в bpo-9915).
Повышена производительность декодирования JSON и уменьшено потребление памяти при повторении одной и той же строки для нескольких ключей. Кроме того, при кодировании JSON теперь используется ускорение C, когда аргумент
sort_keys
является истинным.(При участии Антуана Питру в bpo-7451 и Раймонда Хеттингера и Антуана Питру в bpo-10314).
Рекурсивные блокировки (созданные с помощью API
threading.RLock()
) теперь получают преимущества реализации на языке C, которая делает их такими же быстрыми, как и обычные блокировки, и в 10-15 раз быстрее, чем их предыдущая реализация на чистом Python.(Внесено Антуаном Питру; bpo-3001).
Алгоритм быстрого поиска в stringlib теперь используется методами
split()
,rsplit()
,splitlines()
иreplace()
на объектахbytes
,bytearray
иstr
. Аналогично, алгоритм также используетсяrfind()
,rindex()
,rsplit()
иrpartition()
.Преобразования целых чисел в строки теперь выполняются по две «цифры» за раз, что уменьшает количество операций деления и модуляции.
(bpo-6713) Гавейн Болтон, Марк Дикинсон и Виктор Стиннер.
Было произведено еще несколько незначительных оптимизаций. Дифференцирование множеств теперь работает быстрее, когда один операнд намного больше другого (исправление Андресса Беннетса в bpo-8685). Метод array.repeat()
имеет более быструю реализацию (bpo-1569291 от Александра Белопольского). Метод BaseHTTPRequestHandler
имеет более эффективную буферизацию (bpo-3709 от Andrew Schaaf). Функция operator.attrgetter()
была ускорена (bpo-10160 от Christos Georgiou). И ConfigParser
немного быстрее загружает многострочные аргументы (bpo-7113 от Лукаша Ланги).
Юникод¶
Python был обновлен до Unicode 6.0.0. Обновление стандарта добавляет более 2 000 новых символов, включая символы emoji, которые важны для мобильных телефонов.
Кроме того, обновленный стандарт изменил свойства двух символов языка каннада (U+0CF1, U+0CF2) и одного цифрового символа языка Новый Тай Лю (U+19DA), сделав первые допустимыми для использования в идентификаторах, а вторые дисквалифицировав. Для получения дополнительной информации см. раздел Unicode Character Database Changes.
Кодеки¶
Добавлена поддержка арабской DOS-кодировки cp720 (bpo-1616979).
Кодирование MBCS больше не игнорирует аргумент обработчика ошибок. В строгом режиме по умолчанию она выдает UnicodeDecodeError
, когда встречает недекодируемую последовательность байтов, и UnicodeEncodeError
для некодируемого символа.
Кодек MBCS поддерживает обработчики ошибок 'strict'
и 'ignore'
для декодирования и 'strict'
и 'replace'
для кодирования.
Чтобы эмулировать кодирование MBCS в Python3.1, выберите обработчик 'ignore'
для декодирования и обработчик 'replace'
для кодирования.
В Mac OS X Python декодирует аргументы командной строки с помощью 'utf-8'
, а не кодировки локали.
По умолчанию tarfile
использует кодировку 'utf-8'
в Windows (вместо 'mbcs'
) и обработчик ошибок 'surrogateescape'
во всех операционных системах.
Документация¶
Документация продолжает совершенствоваться.
В верхней части длинных разделов, таких как Встроенные функции, добавлена таблица быстрых ссылок. В случае
itertools
ссылки сопровождаются таблицами с кратким описанием в стиле шпаргалок, чтобы обеспечить обзор и тренировку памяти без необходимости читать всю документацию.В некоторых случаях чистый исходный код Python может быть полезным дополнением к документации, поэтому сейчас многие модули имеют быстрые ссылки на последнюю версию исходного кода. Например, документация модуля
functools
имеет быструю ссылку в верхней части с надписью:Исходный код Lib/functools.py.
(Внесено Раймондом Хеттингером; см. rationale).
Документация теперь содержит больше примеров и рецептов. В частности, модуль
re
имеет обширный раздел Примеры регулярных выражений. Аналогично, модульitertools
продолжает пополняться новыми разделами Рецепты Itertools.Модуль
datetime
теперь имеет вспомогательную реализацию на чистом Python. Никакая функциональность не была изменена. Это просто предоставляет более легкую для чтения альтернативную реализацию.(Внесено Александром Белопольским в bpo-9528).
Не поддерживаемый каталог
Demo
был удален. Некоторые демонстрации были интегрированы в документацию, некоторые были перемещены в каталогTools/demo
, а другие были удалены совсем.(Внесено Георгом Брандлом из bpo-7962).
IDLE¶
Репозиторий кода¶
В дополнение к существующему репозиторию кода Subversion по адресу https://svn.python.org теперь существует репозиторий Mercurial по адресу https://hg.python.org/.
После выхода версии 3.2 планируется переход на Mercurial в качестве основного репозитория. Эта распределенная система контроля версий должна облегчить членам сообщества создание и обмен внешними наборами изменений. Подробности смотрите в PEP 385.
Чтобы научиться пользоваться новой системой контроля версий, смотрите Quick Start или Guide to Mercurial Workflows.
Изменения в API Build и C¶
Изменения в процессе сборки Python и в C API включают:
Скрипты idle, pydoc и 2to3 теперь устанавливаются с суффиксом, зависящим от версии, на
make altinstall
(bpo-10679).Функции C, обращающиеся к базе данных Unicode, теперь принимают и возвращают символы из полного диапазона Unicode, даже при узких сборках Unicode (Py_UNICODE_TOLOWER, Py_UNICODE_ISDECIMAL и другие). Заметное отличие в Python заключается в том, что
unicodedata.numeric()
теперь возвращает правильное значение для больших кодовых точек, аrepr()
может рассматривать больше символов как пригодные для печати.(Сообщено Bupjoe Lee и исправлено Amaury Forgeot D’Arc; bpo-5127).
Вычисляемые gotos теперь включены по умолчанию на поддерживаемых компиляторах (которые определяются скриптом configure). Их по-прежнему можно отключить выборочно, указав
--without-computed-gotos
.(Внесено Антуаном Питру; bpo-9203).
Опция
--with-wctype-functions
была удалена. Встроенная база данных юникода теперь используется для всех функций.(Внесено Амори Форжо Д’Арк; bpo-9210).
Значения хэша теперь являются значениями нового типа,
Py_hash_t
, который определяется как указатель. Ранее они имели тип long, который в некоторых 64-битных операционных системах все еще имеет длину только 32 бита. В результате этого исправления,set
иdict
теперь могут содержать более2**32
записей на сборках с 64-битными указателями (ранее они могли расти до такого размера, но их производительность катастрофически падала).(Предложено Раймондом Хеттингером и реализовано Бенджамином Петерсоном; bpo-9778).
Новый макрос
Py_VA_COPY
копирует состояние списка аргументов переменной. Он эквивалентен C99 va_copy, но доступен на всех платформах Python (bpo-2443).Новая функция C API
PySys_SetArgvEx()
позволяет встроенному интерпретатору устанавливатьsys.argv
без измененияsys.path
(bpo-5753).PyEval_CallObject
теперь доступен только в виде макроса. Объявление функции, которое было сохранено из соображений обратной совместимости, теперь удалено - макрос был введен в 1997 году (bpo-8276).Существует новая функция
PyLong_AsLongLongAndOverflow()
, которая аналогичнаPyLong_AsLongAndOverflow()
. Они обе служат для преобразования Pythonint
в собственный тип фиксированной ширины, обеспечивая при этом обнаружение случаев, когда преобразование не подходит (bpo-7767).Функция
PyUnicode_CompareWithASCIIString()
теперь возвращает не равно, если строка Python завершена NUL.Существует новая функция
PyErr_NewExceptionWithDoc()
, которая подобнаPyErr_NewException()
, но позволяет указать строку документа. Это позволяет исключениям C иметь такие же возможности самодокументирования, как и их чисто питоновские аналоги (bpo-7033).При компиляции с опцией
--with-valgrind
аллокатор pymalloc будет автоматически отключен при работе под Valgrind. Это позволяет улучшить обнаружение утечек памяти при работе под Valgrind, одновременно используя преимущества pymalloc в другое время (bpo-2422).Удален формат
O?
из функций PyArg_Parse. Этот формат больше не используется и никогда не был документирован (bpo-8837).
В C-API был внесен ряд других небольших изменений. Полный список смотрите в файле Misc/NEWS.
Также был внесен ряд обновлений в сборку для Mac OS X, подробности см. в Mac/BuildScript/README.txt. Для пользователей, работающих с 32/64-битной сборкой, известна проблема с Tcl/Tk по умолчанию в Mac OS X 10.6. Соответственно, мы рекомендуем установить обновленную альтернативу, такую как ActiveState Tcl/Tk 8.5.9. Дополнительные сведения см. на сайте https://www.python.org/download/mac/tcltk/.
Перенос на Python 3.2¶
В этом разделе перечислены ранее описанные изменения и другие исправления, которые могут потребовать внесения изменений в ваш код:
Модуль
configparser
подвергся ряду чисток. Основным изменением является замена старого классаConfigParser
на давно предпочитаемую альтернативуSafeConfigParser
. Кроме того, есть ряд небольших несовместимостей:Синтаксис интерполяции теперь проверяется на операциях
get()
иset()
. В схеме интерполяции по умолчанию допустимы только две лексемы со знаками процентов:%(name)s
и%%
, причем последний является экранированным знаком процента.Методы
set()
иadd_section()
теперь проверяют, являются ли значения действительными строками. Ранее неподдерживаемые типы могли быть введены непреднамеренно.Дубликаты разделов или опций из одного источника теперь вызывают либо
DuplicateSectionError
, либоDuplicateOptionError
. Раньше дубликаты молча перезаписывали предыдущую запись.Инлайн-комментарии теперь отключены по умолчанию, поэтому теперь символ ; можно безопасно использовать в значениях.
Комментарии теперь могут иметь отступы. Следовательно, чтобы ; или # появились в начале строки в многострочных значениях, они должны быть интерполированы. Это позволяет не принимать за комментарии префиксные символы в значениях.
""
теперь является допустимым значением и больше не преобразуется автоматически в пустую строку. Для пустых строк используйте"option ="
в строке.
Модуль
nntplib
был сильно переработан, что означает, что его API часто несовместимы с API версии 3.1.Объекты
bytearray
больше нельзя использовать в качестве имен файлов; вместо этого их следует преобразовать вbytes
.array.tostring()
иarray.fromstring()
были переименованы вarray.tobytes()
иarray.frombytes()
для ясности. Старые имена были устаревшими. (См. bpo-8990.)PyArg_Parse*()
функции:Формат «t#» был удален: вместо него используйте «s#» или «s*»
Форматы «w» и «w#» были удалены: вместо них используйте «w*»
Тип
PyCObject
, устаревший в версии 3.1, был удален. Чтобы обернуть непрозрачные указатели C в объекты Python, вместо них следует использовать 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 с промежуточными таблицами перевода соответствующего типа.(Внесено Георгом Брандлом; bpo-5675).
Ранее устаревшая функция
contextlib.nested()
была удалена в пользу простого оператораwith
, который может принимать несколько менеджеров контекста. Последняя техника быстрее (поскольку она встроена) и лучше завершает работу нескольких контекстных менеджеров, когда один из них вызывает исключение:with open('mylog.txt') as infile, open('a.out', 'w') as outfile: for line in infile: if '<critical>' in line: outfile.write(line)
(При участии Георга Брандла и Маттиаса Брандстрема; appspot issue 53094).
struct.pack()
теперь допускает только байты для кода пакета строкs
. Раньше он принимал текстовые аргументы и неявно кодировал их в байты, используя UTF-8. Это было проблематично, поскольку делались предположения о правильной кодировке, а также потому, что кодировка переменной длины может не сработать при записи в сегмент структуры фиксированной длины.Код типа
struct.pack('<6sHHBBB', 'GIF87a', x, y)
должен быть переписан с использованием байтов вместо текста,struct.pack('<6sHHBBB', b'GIF87a', x, y)
.(Обнаружено Дэвидом Бизли и исправлено Виктором Стиннером; bpo-10783).
Класс
xml.etree.ElementTree
теперь выдает сообщениеxml.etree.ElementTree.ParseError
при неудачном разборе. Ранее он выдавал сообщениеxml.parsers.expat.ExpatError
.Новое, более длинное значение
str()
для плавающих значений может нарушить тесты, которые полагаются на старый формат вывода.В
subprocess.Popen
значение по умолчанию для close_fds теперьTrue
под Unix; под Windows оноTrue
, если три стандартных потока установлены вNone
,False
в противном случае. Ранее close_fds по умолчанию всегда былоFalse
, что затрудняло решение ошибок или условий гонки, когда открытые дескрипторы файлов просачивались в дочерний процесс.Поддержка устаревшего HTTP 0.9 была удалена из
urllib.request
иhttp.client
. Такая поддержка все еще присутствует на стороне сервера (вhttp.server
).(Внесено Антуаном Питру, bpo-10711).
SSL-сокеты в режиме таймаута теперь поднимают
socket.timeout
при возникновении таймаута, а не обычноеSSLError
.(Внесено Антуаном Питру, bpo-10272).
Ошибочные функции
PyEval_AcquireLock()
иPyEval_ReleaseLock()
были официально устаревшими. Вместо них следует использовать API с учетом состояния потока (такие какPyEval_SaveThread()
иPyEval_RestoreThread()
).В связи с рисками безопасности функция
asyncore.handle_accept()
была устаревшей, и для ее замены была добавлена новая функцияasyncore.handle_accepted()
.(Внесено Джампаоло Родола из bpo-6706).
Из-за новой реализации GIL,
PyEval_InitThreads()
больше нельзя вызывать передPy_Initialize()
.