Что нового в Python 2.5¶
Автор: | А.М. Кухлинг |
---|
В этой статье объясняются новые возможности Python 2.5. Окончательный релиз Python 2.5 запланирован на август 2006 г.; PEP 356 определяет запланированный график релиза.
Изменения в Python 2.5 представляют собой интересное сочетание
усовершенствований языка и библиотеки. Я думаю, что улучшения в библиотеке
будут более важны для сообщества пользователей Python, потому что было
добавлено несколько широко полезных пакетов. Новые модули включают ElementTree
для обработки XML (xml.etree
), модуль базы данных SQLite (sqlite
)
и модуль ctypes
для вызова функций C.
Языковые изменения имеют среднее значение. Были добавлены некоторые приятные
новые функции, но большинство из них не являются функциями, которые вы будете
использовать каждый день. Наконец, в язык были добавлены условные выражения с
использованием нового синтаксиса; см. раздел PEP 308: условные выражения. Новый оператор
with
упростит написание кода очистки (раздел PEP 343: Оператор with). Теперь
значения можно передавать в генераторы (раздел PEP 342: Новые функции генератора). Импорт теперь
виден как абсолютный или относительный (раздел PEP 328: Абсолютный и относительный импорт). Некоторые
крайние случаи обработки исключений обрабатываются лучше (раздел
PEP 341: Унифицированный try/except/finally). Все данные улучшения имеют смысл, но они являются улучшениями
той или иной языковой функции; ни один из них не является широкой модификацией
семантики Python.
Помимо языковых и библиотечных дополнений, в исходном дереве были внесены другие улучшения и исправления. Поиск в журналах изменений SVN показывает, что между Python 2.4 и 2.5 было применено 353 исправления и исправлено 458 ошибок. (Обе цифры, вероятно, занижены)
Данная статья не претендует на полное описание новых возможностей; вместо этого кратко представлены изменения с использованием полезных примеров. Для получения полной информации вы всегда должны обращаться к документации по Python 2.5 по адресу. Если вы хотите понять полную реализацию и обоснование дизайна, обратитесь к PEP для новой функции.
Комментарии, предложения и отчеты об ошибках для этого документа приветствуются; отправить их автору по электронной почте или открыть сообщение об ошибке в системе отслеживания ошибок Python.
PEP 308: условные выражения¶
В течение долгого времени люди искали способ написания условных выражений, т. е. выражений, которые возвращают значение A или значение B в зависимости от того, является ли логическое значение истинным или ложным. Условное выражение позволяет вам написать один оператор присваивания, который имеет тот же эффект, что и следующий:
if condition:
x = true_value
else:
x = false_value
Были бесконечные утомительные обсуждения синтаксиса как на python-dev, так и на
comp.lang.python. Было даже проведено голосование, которое показало, что
большинство избирателей хотели условных выражений в той или иной форме, но не
было синтаксиса, который предпочитал бы явное большинство. Кандидаты включали C
cond ? true_v : false_v
, if cond then true_v else false_v
и 16 других
вариантов.
Гвидо ван Россумом в конце концов выбрал неожиданный синтаксис:
x = true_value if condition else false_value
Вычисление по-прежнему ленивое, как и в существующих логических выражениях, поэтому порядок вычислений немного меняется. Выражение condition в середине вычисляется первым, а выражение true_value вычисляется, только если условие было истинным. Точно так же выражение false_value вычисляется только в том случае, если условие ложно.
Данный синтаксис может показаться странным и обратным; почему условие идет в
середине выражения, а не в начале, как в C c ? x : y
? Решение было
проверено путём применения нового синтаксиса к модулям в стандартной библиотеке
и просмотра того, как читается получившийся код. Во многих случаях, когда
используется условное выражение, одно значение кажется «общим случаем», а
другое значение — «исключительным случаем», используемым только в более редких
случаях, когда условие не выполняется. Условный синтаксис делает данный шаблон
немного более очевидным:
contents = ((doc + '\n') if doc else '')
Я прочитал приведенное выше утверждение как означающее «здесь contents обычно
присваивается значение doc+'\n'
; иногда doc пуст, и в этом особом случае
возвращается пустая строка». Я сомневаюсь, что буду очень часто использовать
условные выражения там, где нет четкого общего и необычного случая.
Было некоторое обсуждение того, должен ли язык требовать заключения условных выражений в круглые скобки. Было принято решение, что не требует скобок в грамматике языка Python, но с точки зрения стиля я думаю, что вы всегда должны их использовать. Рассмотрим данные два утверждения:
# Первая версия -- без скобок
level = 1 if logging else 0
# Второй вариант -- со скобками
level = (1 if logging else 0)
В первой версии, я думаю, читатель мог бы сгруппировать оператор в «level = 1», «если logging», «иначе 0» и подумать, что условие решает, выполняется ли присвоение level. Второй вариант, на мой взгляд, читается лучше, потому что дает понять, что присваивание выполняется всегда и выбор делается между двумя значениями.
Ещё одна причина включения квадратных скобок: несколько странных комбинаций списков и лямбда-выражений могут выглядеть как неправильные условные выражения. Некоторые примеры см. в PEP 308. Если вы заключаете условные выражения в круглые скобки, вы не столкнетесь с этим случаем.
См.также
- PEP 308 — Условные выражения
- PEP, написанный Гвидо ван Россумом и Рэймондом Д. Хеттингером; реализован Томасом Воутерс.
PEP 309: Приложение частичной функции¶
Модуль functools
содержит инструменты для функционального
программирования.
Одним из полезных инструментов в этом модуле является функция partial()
.
Для программ, написанных в функциональном стиле, вам иногда может понадобиться
создать варианты существующих функций с заполненными некоторыми параметрами.
Рассмотрим функцию Python f(a, b, c)
; вы можете создать новую функцию
g(b, c)
, эквивалентную f(1, b, c)
. Это называется «частичным
применением функций».
partial()
принимает аргументы (function, arg1, arg2, ... kwarg1=value1,
kwarg2=value2)
. Результирующий объект доступен для вызова, поэтому вы можете
просто вызвать его, чтобы вызвать function с заполненными аргументами.
Вот небольшой, но реалистичный пример:
import functools
def log (message, subsystem):
"Записать содержимое 'message' в указанную подсистему."
print '%s: %s' % (subsystem, message)
...
server_log = functools.partial(log, subsystem='server')
server_log('Unable to open socket')
Вот ещё один пример из программы, использующей PyGTK. Здесь контекстно-
зависимое всплывающее меню строится динамически. Обратный вызов,
предоставленный для параметра меню, является частично примененной версией
метода open_item()
, где был предоставлен первый аргумент.
...
class Application:
def open_item(self, path):
...
def init (self):
open_func = functools.partial(self.open_item, item_path)
popup_menu.append( ("Open", open_func, 1) )
Ещё одна функция в модуле functools
— это функция
update_wrapper(wrapper, wrapped)
, которая помогает писать корректные
декораторы. update_wrapper()
копирует атрибут name, module и docstring в
функцию-оболочку, чтобы облегчить понимание обратной трассировки внутри
функции-оболочки. Например, вы можете написать:
def my_decorator(f):
def wrapper(*args, **kwds):
print 'Calling decorated function'
return f(*args, **kwds)
functools.update_wrapper(wrapper, f)
return wrapper
wraps()
— это декоратор, который можно использовать внутри ваших
собственных декораторов для копирования информации обернутой функции.
Альтернативной версией предыдущего примера будет:
def my_decorator(f):
@functools.wraps(f)
def wrapper(*args, **kwds):
print 'Calling decorated function'
return f(*args, **kwds)
return wrapper
См.также
- PEP 309 — Приложение с частичной функциональностью
- PEP, предложенный и написанный Питером Харрисом; реализован Хе-Шик Чанг и Ник Коглана с адаптацией Рэймонда Хеттингера.
PEP 314: Метаданные для программных пакетов Python v1.1¶
В Distutils была добавлена некоторая поддержка простых зависимостей. Функция
setup()
теперь имеет ключевые параметры requires
, provides
и
obsoletes
. При сборке исходного дистрибутива с помощью команды sdist
информация о зависимостях будет записана в файл PKG-INFO
.
Другой новый ключевой параметр — download_url
, который должен быть
установлен на URL-адрес исходного кода пакета. Это означает, что теперь можно
найти запись в указателе пакетов, определить зависимости для пакета и загрузить
необходимые пакеты.
VERSION = '1.0'
setup(name='PyPackage',
version=VERSION,
requires=['numarray', 'zlib (>=1.1.4)'],
obsoletes=['OldPackage']
download_url=('http://www.example.com/pypackage/dist/pkg-%s.tar.gz'
% VERSION),
)
Ещё одно новое усовершенствование индекса пакетов Python на https://pypi.org — это сохранение исходных и двоичных архивов для пакета. Новая команда upload Distutils загрузит пакет в репозиторий.
Перед загрузкой пакета вы должны иметь возможность собрать дистрибутив с
помощью команды sdist Distutils. Как только это сработает, вы можете
запустить python setup.py upload
, чтобы добавить свой пакет в архив PyPI.
При желании вы можете подписать пакет GPG, указав параметры --sign
и
--identity
.
Загрузку пакетов реализовали Мартин фон Лёвис и Ричард Джонс.
См.также
- PEP 314 — метаданные для программных пакетов Python v1.1
- PEP, предложенный и написанный А.М. Кухлинг, Ричард Джонс и Фред Дрейк; реализованный Ричардом Джонсом и Фредом Дрейком.
PEP 328: Абсолютный и относительный импорт¶
Более простая часть PEP 328 была реализована в Python 2.4: теперь можно было
использовать круглые скобки для заключения имён, импортированных из модуля с
помощью оператора from ... import ...
, что упростило импорт множества
разных имён.
Более сложная часть была реализована в Python 2.5: при импорте модуля можно указать использование абсолютного импорта или импорта относительно пакета. План состоит в том, чтобы сделать абсолютный импорт по умолчанию в будущих версиях Python.
Допустим, у вас есть такой каталог пакетов:
pkg/
pkg/__init__.py
pkg/main.py
pkg/string.py
Это определяет пакет с именем pkg
, содержащий подмодули pkg.main
и pkg.string
.
Рассмотрим код в модуле main.py
. Что произойдет, если он выполнит
оператор import string
? В Python 2.4 и более ранних версиях он сначала
просматривает каталог пакета для выполнения относительного импорта, находит
pkg/string.py
, импортирует содержимое этого файла как модуль
pkg.string
, и данный модуль привязан к имени string
в пространстве
имён модуля pkg.main
.
Это нормально, если pkg.string
был тем, что вы хотели. Но что, если вам
нужен стандартный модуль Python string
? Нет простого способа
игнорировать pkg.string
и искать стандартный модуль; вообще надо было
смотреть содержимое sys.modules
, что немного нечисто. Пакет py.std
от Holger Krekel обеспечивает более аккуратный способ выполнения импорта из
стандартной библиотеки import py; py.std.string.join()
, но данный пакет
доступен не во всех установках Python.
Чтение кода, основанного на относительном импорте, также менее понятно, потому
что читатель может не понять, какой модуль, string
или
pkg.string
, предназначен для использования. Пользователи Python вскоре
научились не дублировать имена стандартных библиотечных модулей в именах
подмодулей своих пакетов, но вы не можете защититься от того, чтобы имя вашего
подмодуля использовалось для нового модуля, добавленного в будущую версию
Python.
В Python 2.5 вы можете переключить поведение import
на абсолютный
импорт с помощью директивы from __future__ import absolute_import
. Это
поведение абсолютного импорта станет поведением по умолчанию в будущей версии
(вероятно, Python 2.7). Если по умолчанию используется абсолютный импорт,
import string
всегда будет находить версию стандартной библиотеки.
Предполагается, что пользователи должны начать использовать абсолютный импорт
как можно чаще, поэтому предпочтительнее начинать писать from pkg import
string
в своём коде.
Относительный импорт по-прежнему возможен путём добавления начальной точки к
имени модуля при использовании формы from ... import
:
# Импорт имён из pkg.string
from .string import name1, name2
# Импорт pkg.string
from . import string
Это импортирует модуль string
относительно текущего пакета, поэтому в
pkg.main
будут импортированы name1 и name2 из pkg.string
.
Дополнительные ведущие точки выполняют относительный импорт, начиная с родителя
текущего пакета. Например, код в модуле A.B.C
может подойти:
from . import D # Импортируются A.B.D
from .. import E # Импортируются A.E
from ..F import G # Импортируются A.F.G
Начальные точки нельзя использовать с формой import modname
отчёта об
импорте, только с формой from ... import
.
См.также
- PEP 328 — Импорт: многострочный и абсолютный/относительный
- PEP, написанный Аазом; реализован Томасом Воутерсом.
- https://pylib.readthedocs.io/
- Библиотека py от Хольгер Крикет, содержащая пакет
py.std
.
PEP 338: Выполнение модулей как сценариев¶
Переключатель -m
, добавленный в Python 2.4 для выполнения модуля,
поскольку скрипт получил несколько дополнительных возможностей. Вместо
реализации в коде C внутри интерпретатора Python переключатель теперь использует
реализацию в новом модуле runpy
.
Модуль runpy
реализует более сложный механизм импорта, так что теперь
можно запускать модули в пакете, таком как pychecker.checker
. Модуль
также поддерживает альтернативные механизмы импорта, такие как модуль
zipimport
. Это означает, что вы можете добавить путь ZIP-архива к
sys.path
, а затем использовать переключатель -m
для выполнения
кода из архива.
См.также
- PEP 338 — Выполнение модулей как скриптов
- PEP написан и реализован Ником Когланом.
PEP 341: Унифицированный try/except/finally¶
До Python 2.5 оператор try
существовал в двух вариантах. Вы можете
использовать блок finally
, чтобы убедиться, что код всегда
выполняется, или один или несколько блоков except
, чтобы
перехватывать определённые исключения. Вы не могли объединить оба блока
except
и блок finally
, потому что создание правильного
байт-кода для объединенной версии было сложным, и было неясно, какой должна
быть семантика объединенного оператора.
Гвидо ван Россумом провел некоторое время, работая с Java, которая поддерживает
эквивалент объединения блоков except
и блока finally
, и
это прояснило, что должно означать утверждение. В Python 2.5 теперь вы можете
писать:
try:
block-1 ...
except Exception1:
handler-1 ...
except Exception2:
handler-2 ...
else:
else-block
finally:
final-block
Код в block-1 выполняется. Если код вызывает исключение, проверяются
различные блоки except
: если исключение относится к классу
Exception1
, выполняется handler-1; в противном случае, если это
класс Exception2
, выполняется handler-2 и так далее. Если исключение
не вызывается, выполняется else-block.
Независимо от того, что произошло ранее, final-block выполняется после завершения блока кода и обработки любых возникших исключений. Даже если есть ошибка в обработчике исключений или else-block и вызывается новое исключение, код в final-block все ещё выполняется.
См.также
- PEP 341 — объединение try-except и try-finally
- PEP, написанный Георгом Брандлом; реализация Томаса Ли.
PEP 342: Новые функции генератора¶
В Python 2.5 добавлен простой способ передачи значений в генератор. Как было представлено в Python 2.3, генераторы производят только выходные данные; как только код генератора был вызван для создания итератора, не было возможности передать какую-либо новую информацию в функцию при возобновлении её выполнения. Иногда возможность передать некоторую информацию была бы полезна. Хакерские решения этой проблемы включают в себя то, что код генератора просматривает глобальную переменную, а затем изменяет значение глобальной переменной или передает некоторый изменяемый объект, который затем модифицируется вызывающими объектами.
Чтобы освежить вашу память об основных генераторах, вот простой пример:
def counter (maximum):
i = 0
while i < maximum:
yield i
i += 1
Когда вы вызываете counter(10)
, результатом является итератор, который
возвращает значения от 0 до 9. При обнаружении оператора yield
итератор возвращает предоставленное значение и приостанавливает выполнение
функции, сохраняя локальные переменные. Выполнение возобновляется при следующем
вызове метода итератора next()
после оператора yield
.
В Python 2.3 yield
был оператором; он не вернул никакого значения. В
версии 2.5 yield
теперь является выражением, возвращающим значение,
которое можно присвоить переменной или выполнить другую операцию:
val = (yield i)
Я рекомендую всегда заключать выражение yield
в круглые скобки,
когда вы что-то делаете с возвращаемым значением, как в приведённом выше
примере. Скобки не всегда необходимы, но их всегда проще добавлять, чем
помнить, когда они нужны.
(PEP 342 объясняет точные правила, а именно то, что выражение
yield
всегда должно быть заключено в скобки, за исключением
случаев, когда оно встречается в выражении верхнего уровня в правой части
присваивания. Это означает, что вы можете написать val = yield i
, но должны
использовать круглые скобки. когда есть операция, как в val = (yield i) +
12
.)
Значения отправляются в генератор вызовом его метода send(value)
. Затем код
генератора возобновляется, и выражение yield
возвращает указанный
value. Если вызывается обычный метод next()
, yield
возвращает None
.
Вот предыдущий пример, модифицированный для изменения значения внутреннего счетчика.
def counter (maximum):
i = 0
while i < maximum:
val = (yield i)
# Если указано значение, изменить счётчик
if val is not None:
i = val
else:
i += 1
А вот пример смены счетчика:
>>> it = counter(10)
>>> print it.next()
0
>>> print it.next()
1
>>> print it.send(8)
8
>>> print it.next()
9
>>> print it.next()
Traceback (most recent call last):
File "t.py", line 15, in ?
print it.next()
StopIteration
yield
обычно возвращает None
, поэтому вы всегда должны
проверять данный случай. Не используйте просто его значение в выражениях, если
вы не уверены, что метод send()
будет единственным методом, используемым
для возобновления работы функции генератора.
В дополнение к send()
есть ещё два новых метода для генераторов:
throw(type, value=None, traceback=None)
используется для создания исключения внутри генератора; исключение вызывается выражениемyield
, когда выполнение генератора приостанавливается.close()
вызывает новое исключениеGeneratorExit
внутри генератора, чтобы завершить итерацию. При получении этого исключения код генератора должен вызыватьGeneratorExit
илиStopIteration
. Перехват исключенияGeneratorExit
и возвращение значения недопустимы и вызовут ошибкуRuntimeError
; если функция вызывает какое-либо другое исключение, это исключение передаётся вызывающей стороне.close()
также будет вызываться сборщиком мусора Python при сборке мусора генератором.Если вам нужно запустить код очистки, когда вызывается
GeneratorExit
, я предлагаю использовать пакетtry: ... finally:
вместо перехватаGeneratorExit
.
Кумулятивный эффект данных изменений заключается в том, что генераторы из односторонних производителей информации превращаются как в производителей, так и в потребителей.
Генераторы также становятся корутинами, более обобщенной формой подпрограмм.
Вход в подпрограммы происходит в одной точке, а выход в другой (верхняя часть
функции и оператор return
), но вход в сопрограммы, выход из них и
возобновление работы могут выполняться во многих разных точках (операторы
yield
). Нам нужно выяснить шаблоны для эффективного использования
корутин в Python.
Добавление метода close()
имеет один побочный эффект, который не
очевиден. close()
вызывается, когда генератор подвергается сборке мусора,
поэтому это означает, что код генератора получает последний шанс запуститься
перед тем, как генератор будет уничтожен. Данный последний шанс означает, что
операторы try...finally
в генераторах теперь могут гарантированно работать;
пункт finally
теперь всегда будет выполняться. Таким образом,
синтаксическое ограничение, запрещающее смешивать операторы yield
с
набором try...finally
, было снято. Это кажется незначительным языковым
пустяком, но использование генераторов и try...finally
на самом деле
необходимо для реализации оператора with
, описанного PEP 343. Я
рассмотрю это новое утверждение в следующем разделе.
Другой, ещё более эзотерический эффект этого изменения: ранее атрибут
генератора gi_frame
всегда был объектом фрейма. Теперь возможно, что
gi_frame
станет None
после того, как генератор разрядится.
См.также
- PEP 342 — Корутины через расширенные генераторы
PEP, написанный Гвидо ван Россумом и Филипп Дж. Эби; реализованный Филиппом Дж. Эби. Включает примеры более необычного использования генераторов в качестве корутин.
Более ранние версии данных функций были предложены в PEP 288 Raymond Hettinger и PEP 325 Samuele Pedroni.
- https://en.wikipedia.org/wiki/Корутина
- Запись в Википедии о корутинах.
- http://www.sidhe.org/~dan/blog/archives/000178.html
- Объяснение корутин с точки зрения Perl, написанное Дэном Сугалски.
PEP 343: Оператор with¶
Оператор «with
» разъясняет код, который ранее использовал блоки
try...finally
, чтобы обеспечить выполнение кода очистки. В этом разделе я
расскажу об этом утверждении, поскольку оно будет часто использоваться. В
следующем разделе я рассмотрю детали реализации и покажу, как писать объекты
для использования с этим оператором.
Оператор «with
» — это новая структура потока управления, основная
структура которой такова:
with expression [as variable]:
with-block
Выражение вычисляется, и в результате должен получиться объект, поддерживающий
протокол управления контекстом (т. е. имеющий методы __enter__()
и
__exit__()
.
__enter__()
объекта вызывается перед выполнением with-block и,
следовательно, может запускать код установки. Он также может возвращать
значение, связанное с именем variable, если оно задано. (Обратите внимание,
что variable — не присвоенный результат expression.)
После завершения выполнения with-block вызывается метод объекта
__exit__()
, даже если блок вызвал исключение, и, следовательно, может
выполнять код очистки.
Чтобы включить оператор в Python 2.5, вам нужно добавить следующую директиву в ваш модуль:
from __future__ import with_statement
Оператор всегда будет включён в Python 2.6.
Некоторые стандартные объекты Python теперь поддерживают протокол управления
контекстом и могут использоваться с оператором «with
». Файловые
объекты являются одним из примеров:
with open('/etc/passwd', 'r') as f:
for line in f:
print line
... больше кода обработки ...
После выполнения этого оператора файловый объект в f будет автоматически
закрыт, даже если цикл for
вызвал исключение на полпути через блок.
Примечание
В этом случае f — это тот же объект, созданный open()
, поскольку
file.__enter__()
возвращает self.
Блокировки и условные переменные модуля threading
также поддерживают
оператор with
:
lock = threading.Lock()
with lock:
# Критическая часть кода
...
Блокировка устанавливается перед выполнением блока и всегда снимается после завершения блока.
Новая функция localcontext()
в модуле decimal
позволяет легко
сохранять и восстанавливать текущий десятичный контекст, который инкапсулирует
требуемые характеристики точности и округления для вычислений:
from decimal import Decimal, Context, localcontext
# Отображает с точностью по умолчанию 28 цифр
v = Decimal('578')
print v.sqrt()
with localcontext(Context(prec=16)):
# Весь код в этом блоке использует точность 16 цифр.
# Исходный контекст восстанавливается при выходе из блока.
print v.sqrt()
Написание менеджеров контекста¶
Под капотом оператор «with
» довольно сложен. Большинство людей будут
использовать «with
» только в компании с существующими объектами, и
им не нужно знать данные подробности, поэтому вы можете пропустить оставшуюся
часть этого раздела, если хотите. Авторы новых объектов должны понимать детали
базовой реализации и должны продолжать чтение.
Высокоуровневое объяснение протокола управления контекстом:
- Выражение вычисляется и должно привести к объекту, который называется
«менеджер контекста». Менеджер контекста должен иметь методы
__enter__()
и__exit__()
. - Вызывается метод
__enter__()
менеджера контекста. Возвращаемое значение присваивается VAR. Если предложение'as VAR'
отсутствует, значение просто отбрасывается. - Код в BLOCK выполняется.
- Если BLOCK вызывает исключение, вызывается
__exit__(type, value, traceback)
с подробностями исключения, те же значения возвращаютсяsys.exc_info()
. Возвращаемое значение метода определяет, будет ли повторно вызываться исключение: любое ложное значение повторно вызывает исключение, аTrue
приведёт к его подавлению. Вы редко захотите подавить исключение, потому что, если вы сделаете это, автор кода, содержащего оператор «with
», никогда не поймет, что что-то пошло не так. - Если BLOCK не вызывает исключения, метод
__exit__()
по-прежнему вызывается, но type, value и traceback — всеNone
.
Давайте подумаем на примере. Я не буду приводить подробный код, а лишь набросаю методы, необходимые для базы данных, поддерживающей транзакции.
(Для людей, незнакомых с терминологией баз данных: множество изменений в базе данных группируется в транзакцию. Транзакции могут быть либо зафиксированы, что означает, что все изменения записываются в базу данных, либо отброшены, что означает, что все изменения отбрасываются и база данных не изменилась. Дополнительную информацию см. в любом учебнике по базам данных.)
Предположим, что есть объект, представляющий соединение с базой данных. Наша цель будет состоять в том, чтобы позволить пользователю писать такой код:
db_connection = DatabaseConnection()
with db_connection as cursor:
cursor.execute('insert into ...')
cursor.execute('delete from ...')
# ... больше действий ...
Транзакция должна быть зафиксирована, если код в блоке работает без сбоев, или
отменена, если есть исключение. Вот базовый интерфейс для
DatabaseConnection
, который я предполагаю:
class DatabaseConnection:
# Интерфейс базы данных
def cursor (self):
"Возвращает объект курсора и запускает новую транзакцию"
def commit (self):
"Фиксирует текущую транзакцию"
def rollback (self):
"Откатывает текущую транзакцию"
Метод __enter__()
довольно прост, нужно только начать новую транзакцию.
Для этого приложения результирующий объект курсора будет полезным результатом,
поэтому метод вернёт его. Затем пользователь может добавить as cursor
к
своему оператору «with
», чтобы привязать курсор к имени переменной.
class DatabaseConnection:
...
def __enter__ (self):
# Код для начала новой транзакции
cursor = self.cursor()
return cursor
Метод __exit__()
является самым сложным, поскольку именно с ним
приходится выполнять большую часть работы. Метод должен проверить, произошло ли
исключение. Если исключения не было, транзакция фиксируется. Транзакция
откатывается, если возникло исключение.
В приведённом ниже коде выполнение просто упадет с конца функции, возвращая
значение по умолчанию None
. None
имеет значение ложь, поэтому
исключение будет сгенерировано автоматически. Если вы хотите, вы можете быть
более явным и добавить оператор return
в отмеченном месте.
class DatabaseConnection:
...
def __exit__ (self, type, value, tb):
if tb is None:
# Не исключение, так что коммит
self.commit()
else:
# Произошло исключение, поэтому откат.
self.rollback()
# return False
Модуль contextlib¶
Новый модуль contextlib
предоставляет некоторые функции и декоратор,
полезные для написания объектов для использования с оператором with
.
Декоратор называется contextmanager()
и позволяет вам написать одну
функцию-генератор вместо определения нового класса. Генератор должен выдать
ровно одно значение. Код до yield
будет выполняться как метод
__enter__()
, а полученное значение будет возвращаемым значением метода,
которое будет привязано к переменной в предложении as
оператора
«with
», если таковое имеется. Код после yield
будет
выполняться в методе __exit__()
. Любое исключение, вызванное в блоке,
будет вызвано оператором yield
.
Наш пример базы данных из предыдущего раздела может быть написан с использованием этого декоратора как:
from contextlib import contextmanager
@contextmanager
def db_transaction (connection):
cursor = connection.cursor()
try:
yield cursor
except:
connection.rollback()
raise
else:
connection.commit()
db = DatabaseConnection()
with db_transaction(db) as cursor:
...
Модуль contextlib
также имеет функцию nested(mgr1, mgr2, ...)
,
которая объединяет несколько менеджеров контекста, поэтому вам не нужно писать
вложенные операторы «with
». В этом примере один оператор
«with
» запускает транзакцию базы данных и получает блокировку
потока:
lock = threading.Lock()
with nested (db_transaction(db), lock) as (cursor, locked):
...
Наконец, функция closing(object)
возвращает object, чтобы её можно было
связать с переменной, и вызывает object.close
в конце блока.
import urllib, sys
from contextlib import closing
with closing(urllib.urlopen('http://www.yahoo.com')) as f:
for line in f:
sys.stdout.write(line)
См.также
- PEP 343 — Оператор with
- PEP, написанный Гвидо ван Россумом и Nick Coghlan; реализованный Майком Блэндом
Гвидо ван Россумом и Нил Норвиц. PEP показывает код, сгенерированный для a
Оператор «
with
», который может быть полезен при изучении того, как оператор работает.
Документация для модуля contextlib
.
PEP 352: исключения как классы нового стиля¶
Классы исключений теперь могут быть классами нового стиля, а не только
классическими классами, а встроенный класс Exception
и все стандартные
встроенные исключения (NameError
, ValueError
и т. д.) теперь
являются классами нового стиля.
Немного изменена иерархия наследования исключений. В версии 2.5 отношения наследования такие:
|- KeyboardInterrupt
|- SystemExit
|- Exception
BaseException # новое в Python 2.5
|- (все остальные текущие встроенные исключения)
Реорганизация была сделана потому, что люди часто хотят перехватывать все
исключения, указывающие на ошибки программы. Однако KeyboardInterrupt
и
SystemExit
не являются ошибками и обычно представляют явное действие,
такое как нажатие пользователем Control-C или код, вызывающий
sys.exit()
. Пустой except:
будет перехватывать все исключения,
поэтому вам обычно нужно перечислить KeyboardInterrupt
и
SystemExit
, чтобы повторно вызывать их. Обычная схема такая:
try:
...
except (KeyboardInterrupt, SystemExit):
raise
except:
# Журналирование ошибки ...
# Продолжить выполнение программы...
В Python 2.5 теперь вы можете написать except Exception
для достижения того
же результата, перехватив все исключения, которые обычно указывают на ошибки,
но оставив только KeyboardInterrupt
и SystemExit
. Как и в
предыдущих версиях, голый except:
по-прежнему перехватывает все исключения.
Цель Python 3.0 — потребовать, чтобы любой класс, вызванный как исключение,
производился от BaseException
или какого-либо потомка
BaseException
, и будущие релизы серии Python 2.x могут начать применять
это ограничение. Поэтому я предлагаю вам начать делать все ваши классы
исключений производными от Exception
прямо сейчас. Было предложено
удалить пустую форму except:
в Python 3.0, но Гвидо ван Россумом ещё не
решил, делать это или нет.
Вызов строк как исключений, как в операторе raise "Error occurred"
, устарел
в Python 2.5 и вызовет предупреждение. Цель состоит в том, чтобы иметь
возможность удалить функцию строковых исключений в нескольких выпусках.
См.также
- PEP 352 — обязательный суперкласс для исключений
- PEP, написанный Бреттом Кэнноном и Гвидо ван Россумом; реализован Бреттом Кэнноном.
PEP 353: Использование ssize_t в качестве типа индекса¶
Масштабное изменение Python C API с использованием нового определения типа
Py_ssize_t
вместо int
позволит интерпретатору обрабатывать
больше данных на 64-битных платформах. Это изменение не влияет на возможности
Python на 32-разрядных платформах.
Различные части интерпретатора Python использовали тип C int
для
хранения размеров или количества; например, количество элементов в списке или
кортеже было сохранено в int
. Компиляторы C для большинства 64-битных
платформ по-прежнему определяют int
как 32-битный тип, а это
означает, что списки могут содержать только до 2**31 - 1
= 2147483647
элементов. (На самом деле существует несколько разных моделей программирования,
которые могут использовать 64-битные компиляторы C — см.
http://www.unix.org/version2/whatsnew/lp64_wp.html для обсуждения — но наиболее
распространенная модель оставляет int
. как 32 бит.)
Ограничение в 2 147 483 647 элементов на 32-битной платформе не имеет большого
значения, потому что вам не хватит памяти, прежде чем вы достигнете предела
длины. Для каждого элемента списка требуется место для указателя (4 байта) плюс
место для PyObject
, представляющего элемент. 2147483647*4 — это уже
больше байтов, чем может содержать 32-битное адресное пространство.
Однако можно адресовать такой объем памяти на 64-битной платформе. Указатели
для списка такого размера потребуют всего 16 ГиБ пространства, поэтому вполне
разумно, что программисты Python могут создавать такие большие списки. Поэтому
интерпретатор Python пришлось изменить, чтобы использовать какой-либо тип,
отличный от int
, и это будет 64-битный тип на 64-битных платформах.
Это изменение вызовет несовместимость на 64-битных машинах, поэтому было решено
сделать переход сейчас, пока число 64-битных пользователей все ещё относительно
невелико. (Через 5 или 10 лет мы можем использовать все на 64-битных машинах,
и тогда переход будет более болезненным.)
Это изменение сильнее всего затронет авторов модулей расширения C. Строки
Python и типы контейнеров, такие как списки и кортежи, теперь используют
Py_ssize_t
для хранения своего размера. Такие функции, как
PyList_Size()
, теперь возвращают Py_ssize_t
. Поэтому код в
модулях расширения может потребовать изменения некоторых переменных на
Py_ssize_t
.
Функции PyArg_ParseTuple()
и Py_BuildValue()
имеют новый код
преобразования n
для Py_ssize_t
. s#
и t#
PyArg_ParseTuple()
по-прежнему выводят int
по умолчанию, но
вы можете определить макрос PY_SSIZE_T_CLEAN
перед включением
Python.h
, чтобы они возвращали Py_ssize_t
.
В PEP 353 есть раздел с рекомендациями по преобразованию, которые следует прочитать авторам расширений, чтобы узнать о поддержке 64-разрядных платформ.
См.также
- PEP 353 — использование ssize_t в качестве типа индекса
- PEP написан и реализован Мартином фон Лёвисом.
PEP 357: метод __index__¶
У разработчиков NumPy возникла проблема, которую можно было решить, только
добавив новый специальный метод __index__()
. При использовании нотации
среза, как в [start:stop:step]
, значения индексов start, stop и step
должны быть целыми или длинными целыми числами. NumPy определяет множество
специализированных целочисленных типов, соответствующих целым числам без знака
и со знаком размером 8, 16, 32 и 64 бита, но не было способа указать, что
данные типы можно использовать в качестве индексов срезов.
Нарезка не может просто использовать существующий метод __int__()
, потому
что данный метод также используется для реализации приведения к целым числам.
Если бы для нарезки использовался __int__()
, числа с плавающей запятой
также стали бы допустимыми индексами срезов, а это явно нежелательное
поведение.
Вместо этого был добавлен новый специальный метод __index__()
. Он не
принимает аргументов и возвращает целое число, задающее используемый индекс
среза. Например:
class C:
def __index__ (self):
return self.value
Возвращаемое значение должно быть целым числом Python или длинным целым числом.
Интерпретатор проверит правильность возвращаемого типа и выдаст
TypeError
, если это требование не будет выполнено.
Соответствующий слот nb_index
был добавлен в структуру
PyNumberMethods
уровня C, чтобы позволить расширениям C реализовать
данный протокол. PyNumber_Index(obj)
можно использовать в коде расширения
для вызова функции __index__()
и получения её результата.
См.также
- PEP 357 — Разрешение использования любого объекта для нарезки
- PEP написан и реализован Трэвисом Олифантом.
Другие языковые изменения¶
Вот все изменения, которые Python 2.5 вносит в основной язык Python.
Тип
dict
имеет новый хук, позволяющий подклассам предоставлять значение по умолчанию, когда ключ не содержится в словаре. Если ключ не найден, будет вызван метод словаря__missing__(key)
. Данный хук используется для реализации нового классаdefaultdict
в модулеcollections
. В следующем примере определяется словарь, который возвращает ноль для любого отсутствующего ключа:class zerodict (dict): def __missing__ (self, key): return 0 d = zerodict({1:1, 2:2}) print d[1], d[2] # Prints 1, 2 print d[3], d[4] # Prints 0, 0
И 8-битные строки, и строки Юникод имеют новые методы
partition(sep)
иrpartition(sep)
, которые упрощают общий вариант использования.Метод
find(S)
часто используется для получения индекса, который затем используется для нарезки строки и получения фрагментов до и после разделителя.partition(sep)
объединяет данный шаблон в один вызов метода, который возвращает 3-кортеж, содержащий подстроку перед разделителем, сам разделитель и подстроку после разделителя. Если разделитель не найден, первым элементом кортежа является вся строка, а два других элемента пусты.rpartition(sep)
также возвращает тройку, но начинает поиск с конца строки;r
означает «реверс».Несколько примеров:
>>> ('http://www.python.org').partition('://') ('http', '://', 'www.python.org') >>> ('file:/usr/share/doc/index.html').partition('://') ('file:/usr/share/doc/index.html', '', '') >>> (u'Subject: a quick question').partition(':') (u'Subject', u':', u' a quick question') >>> 'www.python.org'.rpartition('.') ('www.python', '.', 'org') >>> 'www.python.org'.rpartition(':') ('', '', 'www.python.org')
(Реализовано Фредриком Лундом по предложению Рэймонда Хеттингера.)
Методы строковых типов
startswith()
иendswith()
теперь принимают кортежи строк для проверки.def is_image_file (filename): return filename.endswith(('.gif', '.jpg', '.tiff'))
(Реализовано Георгом Брандлом по предложению Тома Линна.)
Встроенные функции
min()
иmax()
получили ключевой параметрkey
, аналогичный аргументуkey
дляsort()
. Данный параметр предоставляет функцию, которая принимает один аргумент и вызывается для каждого значения в списке;min()
/max()
вернёт элемент с наименьшим/наибольшим возвращаемым значением из этой функции. Например, чтобы найти самую длинную строку в списке, вы можете сделать это:L = ['medium', 'longest', 'short'] # Печатает 'longest' print max(L, key=len) # Печатает 'short', потому что лексикографически 'short' имеет наибольшее значение print max(L)
(Предоставлено Стивеном Бетардом и Рэймондом Хеттингером.)
Две новые встроенные функции
any()
иall()
, вычисляют, содержит ли итератор какие-либо значения истина или ложь.any()
возвращаетTrue
, если любое значение, возвращаемое итератором, истинно; в противном случае он вернётFalse
.all()
возвращаетTrue
, только если все значения, возвращаемые итератором, вычисляются как истинные. (Предложено Гвидо ван Россумом и реализовано Рэймондом Хеттингером.)Результатом метода класса
__hash__()
теперь может быть либо длинное целое число, либо обычное целое число. Если возвращается длинное целое число, берется хэш этого значения. В более ранних версиях хеш-значение должно было быть обычным целым числом, но в версии 2.5 встроенныйid()
был изменён, чтобы всегда возвращать неотрицательные числа, и пользователи часто используютid(self)
в методах__hash__()
(хотя это не рекомендуется).ASCII теперь является кодировкой по умолчанию для модулей. Теперь это синтаксическая ошибка, если модуль содержит строковые литералы с 8-битными символами, но не имеет объявления кодировки. В Python 2.4 это вызвало предупреждение, а не синтаксическую ошибку. См. PEP 263, чтобы узнать, как объявить кодировку модуля; например, вы можете добавить такую строку вверху исходного файла:
# -*- coding: latin1 -*-
Новое предупреждение
UnicodeWarning
выдается при попытке сравнить строку Юникод и 8-битную строку, которую нельзя преобразовать в Юникод с использованием кодировки ASCII по умолчанию. Результат сравнения ложный:>>> chr(128) == unichr(128) # Не удается преобразовать chr(128) в Юникод __main__:1: UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal False >>> chr(127) == unichr(127) # chr(127) можно преобразовать True
Раньше это вызывало исключение
UnicodeDecodeError
, но в версии 2.5 это могло привести к непонятным проблемам при доступе к словарю. Если бы вы искалиunichr(128)
, аchr(128)
использовался в качестве ключа, вы бы получили исключениеUnicodeDecodeError
. Другие изменения в версии 2.5 привели к тому, что это исключение было вызвано, а не подавлено кодом вdictobject.c
, который реализует словари.Вызов исключения для такого сравнения абсолютно корректен, но изменение могло привести к повреждению кода, поэтому вместо этого был введен
UnicodeWarning
.(Реализовано Марком-Андре Лембургом.)
Одна ошибка, которую иногда допускают программисты Python, заключается в том, что они забывают включить модуль
__init__.py
в каталог пакета. Отладка этой ошибки может привести к путанице и обычно требует запуска Python с параметром-v
для регистрации всех найденных путей. В Python 2.5 новое предупреждениеImportWarning
срабатывает, когда импорт должен был выбрать каталог как пакет, но__init__.py
не был найден. Это предупреждение по умолчанию игнорируется; указать параметр-Wd
при запуске исполняемого файла Python для отображения предупреждающего сообщения. (Реализовано Томасом Воутерсом.)Список базовых классов в определении класса теперь может быть пустым. Например, теперь это законно:
class C(): pass
(Реализовано Бреттом Кэнноном.)
Изменения интерактивного интерпретатора¶
В интерактивном интерпретаторе quit
и exit
уже давно являются строками,
так что новые пользователи получают несколько полезное сообщение, когда
пытаются выйти:
>>> quit
'Use Ctrl-D (i.e. EOF) to exit.'
В Python 2.5 quit
и exit
теперь являются объектами, которые по-прежнему
создают строковые представления самих себя, но также могут вызываться. Новички,
которые пробуют quit()
или exit()
, теперь будут выходить из
интерпретатора, как они и ожидали. (Реализовано Георгом Брандлом.)
Исполняемый файл Python теперь принимает стандартные длинные параметры
--help
и --version
; в Windows он также принимает параметр
/?
для отображения справочного сообщения. (Реализовано Георгом
Брандлом.)
Оптимизации¶
Несколько оптимизаций были разработаны во время спринта NeedForSpeed, мероприятия, проходившего в Рейкьявике, Исландия, с 21 по 28 мая 2006 года. Спринт был сосредоточен на повышении скорости реализации CPython и финансировался EWT LLC при местной поддержке CCP Games. Оптимизации, добавленные в этом спринте, отмечены в следующем списке.
- Когда они были представлены в Python 2.4, встроенные типы
set
иfrozenset
были построены поверх словарного типа Python. В версии 2.5 внутренняя структура данных была настроена для реализации наборов, в результате чего наборы будут использовать на треть меньше памяти и работать несколько быстрее. (Реализован Раймондом Хеттингером.) - Повышена скорость некоторых операций Юникод, таких как поиск подстрок, разбиение строк, а также кодирование и декодирование карты символов. (Улучшения поиска подстрок и разделения были добавлены Фредриком Лундом и Эндрю Далке во время спринта NeedForSpeed. Карты символов были улучшены Вальтером Дёрвальдом и Мартином фон Лёвисом.
- Функция
long(str, base)
теперь работает быстрее для длинных строк цифр, поскольку вычисляется меньше промежуточных результатов. Пик приходится на строки из 800-1000 цифр, где функция работает в 6 раз быстрее. (Предоставлено Аланом Макинтайром и зафиксировано в спринте NeedForSpeed. - Теперь незаконно смешивать итерацию по файлу с
for line in file
и вызов методов файлового объектаread()
/readline()
/readlines()
. Итерация использует внутренний буфер, а методыread*()
не используют данный буфер. Вместо этого они будут возвращать данные после буфера, в результате чего данные будут отображаться не по порядку. Смешанная итерация и данные методы теперь вызовутValueError
из методаread*()
. (Реализовано Томасом Воутерсом.) - Модуль
struct
теперь компилирует строки формата структуры во внутреннее представление и кэширует это представление, что дает ускорение на 20%. (Представлено Бобом Ипполито на спринте NeedForSpeed.) - Модуль
re
получил ускорение на 1 или 2% за счет переключения на функции распределителя Python вместо системныхmalloc()
иfree()
. (Представлено Джеком Дидерихом на спринте NeedForSpeed.) - Оптимизатор глазка генератора кода теперь выполняет простое свертывание
констант в выражениях. Если вы напишете что-то вроде
a = 2+3
, генератор кода выполнит арифметические действия и создаст код, соответствующийa = 5
. (Предложено и реализовано Раймондом Хеттингером.) - Вызовы функций теперь выполняются быстрее, поскольку объекты кода теперь сохраняют самый последний законченный фрейм («фрейм зомби») во внутреннем поле объекта кода, повторно используя его при следующем вызове объекта кода. (Исходный патч Майкла Хадсона, измененный Армином Риго и Ричардом Джонсом; добавлен на спринте NeedForSpeed.) Объекты фреймов также немного меньше, что может улучшить локальность кеша и немного уменьшить использование памяти. (Предоставлено Нилом Норвицем.)
- Встроенные исключения Python теперь представляют собой классы нового стиля, изменение, которое значительно ускоряет создание экземпляров. Таким образом, обработка исключений в Python 2.5 примерно на 30% быстрее, чем в версии 2.4. (Предоставлено Ричардом Джонсом, Георгом Брандлом и Шоном Рейфшнайдером на спринте NeedForSpeed)
- Импорт теперь кэширует проверенные пути, записывая, существуют они или нет,
чтобы интерпретатор делал меньше вызовов
open()
иstat()
при запуске. (Предоставлено Мартином фон Лёвисом и Георгом Брандлом)
Новые, улучшенные и удаленные модули¶
Стандартная библиотека получила множество улучшений и исправлений ошибок в
Python 2.5. Вот неполный список наиболее заметных изменений, отсортированных в
алфавитном порядке по имени модуля. Обратитесь к файлу Misc/NEWS
в
исходном дереве для получения более полного списка изменений или просмотрите
все подробности в журналах SVN.
Модуль
audioop
теперь поддерживает кодировку a-LAW, а код для кодировки u-LAW был улучшен. (Предоставлено Ларсом Иммишем.)Модуль
codecs
получил поддержку инкрементных кодеков. Функцияcodec.lookup()
теперь возвращает экземплярCodecInfo
вместо кортежа. ЭкземплярыCodecInfo
ведут себя как 4-кортежи для сохранения обратной совместимости, но также имеют атрибутыencode
,decode
,incrementalencoder
,incrementaldecoder
,streamwriter
иstreamreader
. Инкрементные кодеки могут получать входные данные и создавать выходные данные несколькими порциями; вывод такой же, как если бы весь ввод был передан неинкрементному кодеку. Подробности смотрите в документации модуляcodecs
. (Разработано и реализовано Вальтером Дёрвальдом.)Модуль
collections
получил новый типdefaultdict
, который является подклассом стандартного типаdict
. Новый тип в основном ведёт себя как словарь, но создаёт значение по умолчанию, когда ключ отсутствует, автоматически добавляя его в словарь для запрошенного значения ключа.Первый аргумент конструктора
defaultdict
— это фабричная функция, которая вызывается каждый раз, когда запрашивается ключ, но он не найден. Эта фабричная функция не получает аргументов, поэтому вы можете использовать встроенные конструкторы типов, такие какlist()
илиint()
. Например, вы можете сделать указатель слов на основе их начальной буквы следующим образом:words = """Nel mezzo del cammin di nostra vita mi ritrovai per una selva oscura che la diritta via era smarrita""".lower().split() index = defaultdict(list) for w in words: init_letter = w[0] index[init_letter].append(w)
Печать
index
приводит к следующему результату:defaultdict(<type 'list'>, {'c': ['cammin', 'che'], 'e': ['era'], 'd': ['del', 'di', 'diritta'], 'm': ['mezzo', 'mi'], 'l': ['la'], 'o': ['oscura'], 'n': ['nel', 'nostra'], 'p': ['per'], 's': ['selva', 'smarrita'], 'r': ['ritrovai'], 'u': ['una'], 'v': ['vita', 'via']}
(Предоставлено Гвидо ван Россумом.)
Тип двусторонней очереди
deque
, предоставляемый модулемcollections
, теперь имеет методremove(value)
, удаляющий первое вхождение value в очереди и поднимающийValueError
, если значение не найдено. (Предоставлено Рэймондом Хеттингером.)Новый модуль: модуль
contextlib
содержит вспомогательные функции для использования с новым оператором «with
». Подробнее об этом модуле см. в разделе Модуль contextlib.Новый модуль: модуль
cProfile
— это реализация существующего модуляprofile
на языке C, которая имеет гораздо меньшие накладные расходы. Интерфейс модуля такой же, как уprofile
: вы запускаетеcProfile.run('main()')
для профилирования функции, можете сохранять данные профиля в файл и т. д. Пока неизвестно, работает ли профилировщик Hotshot, который также написан на C, но не соответствует интерфейс, будет по- прежнему поддерживаться в будущих версиях Python. (Предоставлено Армином Риго.)Кроме того, модуль
pstats
для анализа данных, измеренных профилировщиком, теперь поддерживает направление вывода на любой файловый объект путём предоставления аргумента stream конструкторуStats
. (Предоставлено Скипом Монтанаро.)Модуль
csv
, анализирующий файлы в формате значений, разделенных запятыми, получил несколько улучшений и ряд исправлений. Теперь вы можете установить максимальный размер поля в байтах, вызвав функциюcsv.field_size_limit(new_limit)
; отсутствие аргумента new_limit вернёт текущий установленный лимит. Классreader
теперь имеет атрибутline_num
, который подсчитывает количество физических строк, считанных из источника; записи могут охватывать несколько физических строк, поэтомуline_num
не совпадает с количеством прочитанных записей.Парсер CSV теперь строже относится к полям с многострочными кавычками. Ранее, если строка заканчивалась в поле, заключенном в кавычки, без завершающего символа новой строки, в возвращаемое поле вставлялась новая строка. Такое поведение вызывало проблемы при чтении файлов, содержащих символы возврата каретки в полях, поэтому код был изменён, чтобы возвращать поле без вставки новой строки. Как следствие, если символы новой строки, встроенные в поля, важны, ввод должен быть разбит на строки таким образом, чтобы сохранить символы новой строки.
(Предоставили Скип Монтанаро и Эндрю Макнамара.)
Класс
datetime
в модулеdatetime
теперь имеет методstrptime(string, format)
для синтаксического анализа строк даты, предоставленный Джошем Споерри. Он использует те же символы формата, что иtime.strptime()
иtime.strftime()
:from datetime import datetime ts = datetime.strptime('10:13:15 2006-03-07', '%H:%M:%S %Y-%m-%d')
Метод
SequenceMatcher.get_matching_blocks()
в модулеdifflib
теперь гарантирует возвращение минимального списка блоков, определяющих совпадающие подпоследовательности. Раньше алгоритм иногда разбивал блок совпадающих элементов на две записи списка. (Улучшение Тимом Питерсом.)Модуль
doctest
получил параметрSKIP
, который вообще запрещает выполнение примера. Это предназначено для фрагментов кода, которые являются примерами использования, предназначенными для читателя, а не тестовыми примерами.Параметр encoding был добавлен в функцию
testfile()
и классDocFileSuite
для указания кодировки файла. Это упрощает использование символов, отличных от ASCII, в тестах, содержащихся в строке документации. (Предоставлено Бьорном Тиллениусом.)Пакет
email
обновлен до версии 4.0. (Предоставлено Барри Варшавой.)Модуль
fileinput
стал более гибким. Теперь поддерживаются имена файлов в формате Юникод, а параметр mode, который по умолчанию равен"r"
, был добавлен в функциюinput()
, чтобы разрешить открытие файлов в двоичном режиме или в режиме универсального символа новой строки. Ещё один новый параметр, openhook, позволяет использовать функцию, отличную отopen()
, для открытия входных файлов. Как только вы перебираете множество файлов, новыйfileno()
объектаFileInput
возвращает файловый дескриптор для текущего открытого файла. (Предоставлено Георгом Брандлом.)В модуле
gc
новая функцияget_count()
возвращает тройку, содержащую текущие счетчики коллекций для трех поколений GC. Это учетная информация для сборщика мусора; когда данные значения достигают заданного порога, выполняется очистка сборки мусора. Существующая функцияgc.collect()
теперь принимает необязательный аргумент generation, равный 0, 1 или 2, чтобы указать, какое поколение собирать. (Предоставлено Барри Варшавой.)Функции
nsmallest()
иnlargest()
в модулеheapq
теперь поддерживают ключевой параметрkey
, аналогичный параметру, предоставляемому функциямиmin()
/max()
и методамиsort()
. Например:>>> import heapq >>> L = ["short", 'medium', 'longest', 'longer still'] >>> heapq.nsmallest(2, L) # Возвращает два младших элемента лексикографически ['longer still', 'longest'] >>> heapq.nsmallest(2, L, key=len) # Возвращает два кратчайших элемента ['short', 'medium']
(Предоставлено Рэймондом Хеттингером.)
Функция
itertools.islice()
теперь принимаетNone
в качестве аргументов начала и шага. Это делает его более совместимым с атрибутами объектов-срезов, так что теперь вы можете написать следующее:s = slice(5) # Создать объект среза itertools.islice(iterable, s.start, s.stop, s.step)
(Предоставлено Рэймондом Хеттингером.)
Функция
format()
в модулеlocale
была изменена, и были добавлены две новые функции,format_string()
иcurrency()
.Параметр val функции
format()
ранее мог быть строкой, если отображалось не более одного спецификатора %char; теперь параметр должен быть ровно одним спецификатором %char без окружающего текста. Также был добавлен необязательный параметр monetary, который, еслиTrue
, будет использовать правила локали для форматирования валюты при размещении разделителя между группами из трех цифр.Для форматирования строк с несколькими спецификаторами %char используйте новую функцию
format_string()
, которая работает аналогичноformat()
, но также поддерживает смешивание спецификаторов %char с произвольным текстом.Также была добавлена новая функция
currency()
, которая форматирует число в соответствии с настройками текущей локали.(Предоставлено Георгом Брандлом.)
Модуль
mailbox
был значительно переписан, чтобы добавить возможность изменять почтовые ящики в дополнение к их чтению. Новый множество классов, включающийmbox
,MH
иMaildir
, используется для чтения почтовых ящиков и имеет методadd(message)
для добавления сообщений,remove(key)
для удаления сообщений иlock()
/unlock()
для блокировки/разблокировки почтового ящика. В следующем примере почтовый ящик формата maildir преобразуется в формат mbox:import mailbox # 'factory=None' использует email.Message.Message как представляющий класс # отдельные сообщения. src = mailbox.Maildir('maildir', factory=None) dest = mailbox.mbox('/tmp/mbox') for msg in src: dest.add(msg)
(Предоставил Грегори К. Джонсон. Финансирование было предоставлено компанией Google Summer of Code 2005 г.)
Новый модуль: модуль
msilib
позволяет создавать файлы Microsoft Installer.msi
и CAB-файлы. Также включена некоторая поддержка чтения базы данных.msi
. (Предоставлено Мартином фон Лёвисом.)Модуль
nis
теперь поддерживает доступ к доменам, отличным от системного домена по умолчанию, путём предоставления аргумента domain функциямnis.match()
иnis.maps()
. (Предоставлено Беном Беллом.)Функции
itemgetter()
иattrgetter()
модуляoperator
теперь поддерживают несколько полей. Такой вызов, какoperator.attrgetter('a', 'b')
, вернёт функцию, которая извлекает атрибутыa
иb
. Сочетание этой новой функции с параметромkey
методаsort()
позволяет легко сортировать списки с использованием нескольких полей. (Предоставлено Рэймондом Хеттингером.)Модуль
optparse
обновлен до версии 1.5.1 библиотеки Optik. КлассOptionParser
получил атрибутepilog
, строку, которая будет напечатана после справочного сообщения, и методdestroy()
для прерывания циклов ссылок, созданных объектом. (Предоставлено Грегом Уордом.)Модуль
os
претерпел несколько изменений. Переменнаяstat_float_times
теперь по умолчанию имеет значение истина, а это означает, чтоos.stat()
теперь будет возвращать значения времени в виде чисел с плавающей запятой. (Это не обязательно означает, чтоos.stat()
будет возвращать время с точностью до долей секунды; не все системы поддерживают такую точность.)Добавлены константы с именами
os.SEEK_SET
,os.SEEK_CUR
иos.SEEK_END
; это параметры функцииos.lseek()
. Две новые константы для блокировки —os.O_SHLOCK
иos.O_EXLOCK
.Были добавлены две новые функции,
wait3()
иwait4()
. Они похожи на функциюwaitpid()
, которая ожидает завершения дочернего процесса и возвращает кортеж с идентификатором процесса и его статусом выхода, ноwait3()
иwait4()
возвращают дополнительную информацию.wait3()
не принимает идентификатор процесса в качестве входных данных, поэтому он ожидает завершения любого дочернего процесса и возвращает тройку из process-id, exit-status, resource-usage, возвращаемую функциейresource.getrusage()
.wait4(pid)
принимает идентификатор процесса. (Предоставлено Чадом Дж. Шредером.)Во FreeBSD функция
os.stat()
теперь возвращает время с разрешением в наносекунды, а возвращаемый объект теперь имеетst_gen
иst_birthtime
. Также доступен атрибутst_flags
, если платформа его поддерживает. (Предоставили Антти Луко и Диего Петтено.)Отладчик Python, предоставляемый модулем
pdb
, теперь может хранить списки команд для выполнения при достижении точки останова и остановке выполнения. После создания точки останова #1 введитеcommands 1
и серию команд для выполнения, закончив списокend
. Список команд может включать команды, которые возобновляют выполнение, напримерcontinue
илиnext
. (Предоставлено Грегуаром Думсом)Модули
pickle
иcPickle
больше не принимают возвращаемое значениеNone
из метода__reduce__()
; вместо этого метод должен возвращать кортеж аргументов. Возможность возвращатьNone
устарела в Python 2.4, так что это завершает удаление функции.Модуль
pkgutil
, содержащий различные служебные функции для поиска пакетов, был улучшен для поддержки перехватчиков импорта PEP 302 и теперь также работает с пакетами, хранящимися в ZIP-архивах. (Предоставлено Филиппом Дж. Эби.)Множество тестов pybench от Марка-Андре Лембурга теперь включён в каталог
Tools/pybench
. Пакет pybench является усовершенствованием широко используемой программыpystone.py
, поскольку pybench обеспечивает более подробное измерение скорости интерпретатора. Он измеряет время определенных операций, таких как вызовы функций, нарезка кортежей, поиск методов и числовые операции, вместо того, чтобы выполнять множество различных операций и сводить результат к одному числу, как это делаетpystone.py
.Модуль
pyexpat
теперь использует версию 2.0 парсера Expat. (Предоставлено Трентом Миком.)Класс
Queue
, предоставляемый модулемQueue
, получил два новых метода.join()
блокируется до тех пор, пока не будут получены все элементы в очереди и не будет завершена вся работа по обработке элементов. Рабочие потоки вызывают другой новый метод,task_done()
, чтобы сообщить, что обработка элемента завершена. (Предоставлено Рэймондом Хеттингером.)Старые модули
regex
иregsub
, которые устарели ещё со времен Python 2.0, наконец-то удалены. Другие удаленные модули:statcache
,tzparse
,whrandom
.Также удалено: удален каталог
lib-old
, в который входят такие древние модули, какdircmp
иni
.lib-old
не был вsys.path
по умолчанию, поэтому, если ваши программы явно не добавили каталог вsys.path
, это удаление не должно повлиять на ваш код.Модуль
rlcompleter
больше не зависит от импорта модуляreadline
и поэтому теперь работает на платформах, отличных от Unix. (Патч от Роберта Киндла.)Классы
SimpleXMLRPCServer
иDocXMLRPCServer
теперь имеют атрибутrpc_paths
, ограничивающий операции XML-RPC ограниченным набором URL-адресов; по умолчанию разрешены только'/'
и'/RPC2'
. Установкаrpc_paths
вNone
или пустой кортеж отключает эту проверку пути.Модуль
socket
теперь поддерживает сокетыAF_NETLINK
в Linux благодаря патчу от Philippe Biondi. Сокеты Netlink — это специфичный для Linux механизм связи между процессом пользовательского пространства и кодом ядра; вводная статья о них находится по адресу https://www.linuxjournal.com/article/7356. В коде Python адреса сетевых ссылок представлены в виде кортежа из двух целых чисел,(pid, group_mask)
.Два новых метода для объектов сокетов,
recv_into(buffer)
иrecvfrom_into(buffer)
, сохраняют полученные данные в объекте, который поддерживает протокол буфера, вместо того, чтобы возвращать данные в виде строки. Это означает, что вы можете поместить данные непосредственно в массив или в отображаемый в память файл.Объекты Socket также получили методы доступа
getfamily()
,gettype()
иgetproto()
для получения значений семейства, типа и протокола для сокета.Новый модуль: модуль
spwd
предоставляет функции для доступа к базе данных теневых паролей в системах, поддерживающих теневые пароли.struct
теперь работает быстрее, потому что он компилирует строки формата в объектыStruct
с помощью методовpack()
иunpack()
. Это похоже на то, как модульre
позволяет создавать скомпилированные объекты регулярных выражений. Вы по-прежнему можете использовать функции уровня модуляpack()
иunpack()
; они будут создавать объектыStruct
и кэшировать их. Или вы можете напрямую использовать экземплярыStruct
:s = struct.Struct('ih3s') data = s.pack(1972, 187, 'abc') year, number, name = s.unpack(data)
Вы также можете упаковывать и распаковывать данные в буферные объекты и из них напрямую, используя методы
pack_into(buffer, offset, v1, v2, ...)
иunpack_from(buffer, offset)
. Это позволяет хранить данные непосредственно в массиве или в отображаемом в память файле.(Объекты
Struct
были реализованы Бобом Ипполито во время спринта NeedForSpeed. Поддержка объектов буфера была добавлена Мартином Блейсом также во время спринта NeedForSpeed.)Разработчики Python перешли с CVS на Subversion в процессе разработки версии 2.5. Информация о точной версии сборки доступна в виде переменной
sys.subversion
, состоящей из трех кортежей(interpreter-name, branch- name, revision-range)
. Например, на момент написания моя копия 2.5 сообщала('CPython', 'trunk', '45313:45315')
.Информация также доступна для расширений C через функцию
Py_GetBuildInfo()
, которая возвращает строку информации о сборке, например:"trunk:45355:45356M, Apr 13 2006, 07:42:19"
. (Предоставлено Барри Варшавой.)Другая новая функция,
sys._current_frames()
, возвращает текущие фреймы стека для всех запущенных потоков в виде словаря, отображающего идентификаторы потоков на самый верхний фрейм стека, активный в данный момент в этом потоке во время вызова функции. (Предоставлено Тимом Питерсом.)Класс
TarFile
в модулеtarfile
теперь имеет методextractall()
, который извлекает все элементы из архива в текущий рабочий каталог. Также можно установить другой каталог в качестве цели извлечения и распаковать только подмножество членов архива.Сжатие, используемое для tar-файла, открытого в потоковом режиме, теперь может определяться автоматически с использованием режима
'r|*'
. (Предоставлено Ларсом Густебелем.)Модуль
threading
теперь позволяет вам устанавливать размер стека, используемый при создании новых потоков. Функцияstack_size([*size*])
возвращает текущий сконфигурированный размер стека, а предоставление дополнительного параметра size устанавливает новое значение. Не все платформы поддерживают изменение размера стека, но Windows, многопоточность POSIX и OS/2 поддерживают это. (Предоставлено Эндрю Макинтайром.)Модуль
unicodedata
был обновлен для использования версии 4.1.0 базы данных символов Юникод. Версия 3.2.0 требуется некоторыми спецификациями, поэтому она по-прежнему доступна какunicodedata.ucd_3_2_0
.Новый модуль: модуль
uuid
генерирует универсальные уникальные идентификаторы (UUID) в соответствии с RFC 4122. RFC определяет несколько разных версий UUID, которые генерируются из исходной строки, из системных свойств или чисто случайным образом. Данный модуль содержит классUUID
и функции с именамиuuid1()
,uuid3()
,uuid4()
иuuid5()
для создания различных версий UUID. (UUID версии 2 не указаны в RFC 4122 и не поддерживаются этим модулем.)>>> import uuid >>> # сделать UUID на основе идентификатора хоста и текущего времени >>> uuid.uuid1() UUID('a8098c1a-f86e-11da-bd1a-00112444be1e') >>> # создать UUID, используя хэш MD5 UUID пространства имён и имя >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org') UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e') >>> # сделать случайный UUID >>> uuid.uuid4() UUID('16fd2706-8baf-433b-82eb-8c7fada847da') >>> # создать UUID, используя хэш SHA-1 UUID пространства имён и имя >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org') UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')
(Предоставлено Ка-Пинг Йи.)
Типы
WeakKeyDictionary
иWeakValueDictionary
модуляweakref
получили новые методы для перебора слабых ссылок, содержащихся в словаре. Методыiterkeyrefs()
иkeyrefs()
были добавлены кWeakKeyDictionary
, а методыitervaluerefs()
иvaluerefs()
были добавлены кWeakValueDictionary
. (Предоставлено Фредом Л. Дрейком-младшим.)Модуль
webbrowser
получил ряд улучшений. Теперь его можно использовать как сценарий сpython -m webbrowser
, принимая URL-адрес в качестве аргумента; есть ряд переключателей для управления поведением (-n
для нового окна браузера,-t
для нового таба). Для поддержки этого были добавлены новые функции уровня модуля,open_new()
иopen_new_tab()
. Функция модуляopen()
поддерживает дополнительный параметр autoraise сигнализирующий, поднимать ли открытое окно, когда это возможно. В список поддерживаемых был добавлен ряд дополнительных браузеров, таких как Firefox, Opera, Konqueror и elinks. (Предоставлено Олегом Бройтманном и Георгом Брандлом.)Модуль
xmlrpclib
теперь поддерживает возвращение объектовdatetime
для типа даты XML-RPC. Предоставьтеuse_datetime=True
функцииloads()
или классуUnmarshaller
, чтобы включить эту функцию. (Предоставлено Скипом Монтанаро.)Модуль
zipfile
теперь поддерживает версию формата ZIP64, а это означает, что ZIP-архив теперь может иметь размер более 4 ГБ и может содержать отдельные файлы размером более 4 ГБ. (Предоставлено Рональдом Оссореном.)Объекты
Compress
иDecompress
модуляzlib
теперь поддерживают методcopy()
, который создаёт копию внутреннего состояния объекта и возвращает новый объектCompress
илиDecompress
. (Предоставлено Крисом Этли.)
Пакет ctypes¶
Пакет ctypes
, написанный Томасом Хеллером, добавлен в стандартную
библиотеку. ctypes
позволяет вызывать произвольные функции в разделяемых
библиотеках или DLL. Давние пользователи могут помнить модуль dl
,
предоставляющий функции для загрузки разделяемых библиотек и вызова в них
функций. Пакет ctypes
намного интереснее.
Чтобы загрузить общую библиотеку или библиотеку DLL, необходимо создать
экземпляр класса CDLL
и указать имя или путь к общей библиотеке или
библиотеке DLL. После этого вы можете вызывать произвольные функции, обращаясь
к ним как к атрибутам объекта CDLL
.
import ctypes
libc = ctypes.CDLL('libc.so.6')
result = libc.printf("Line of output\n")
Предоставляются конструкторы типов для различных типов C: c_int()
,
c_float()
, c_double()
, c_char_p()
(эквивалентно char
*
) и т. д. В отличие от типов Python, все версии C изменяемы; вы можете
назначить их атрибуту value
, чтобы изменить обернутое значение. Целые
числа и строки Python будут автоматически преобразованы в соответствующие типы
C, но для других типов вы должны вызвать правильный конструктор типа. (И я имею
в виду must; неправильный выбор часто приводит к сбою интерпретатора из-за
ошибки сегментации.)
Вы не должны использовать c_char_p()
со строкой Python, когда функция C
будет изменять область памяти, потому что строки Python должны быть
неизменяемыми; нарушение этого правила вызовет загадочные ошибки. Если вам
нужна изменяемая область памяти, используйте create_string_buffer()
:
s = "this is a string"
buf = ctypes.create_string_buffer(s)
libc.strfry(buf)
Предполагается, что функции C возвращают целые числа, но вы можете установить
атрибут restype
объекта функции, чтобы изменить это:
>>> libc.atof('2.71828')
-1783957616
>>> libc.atof.restype = ctypes.c_double
>>> libc.atof('2.71828')
2.71828
ctypes
также предоставляет оболочку для Python C API в виде объекта
ctypes.pythonapi
. Данный объект not освобождает глобальную блокировку
интерпретатора перед вызовом функции, потому что блокировка должна удерживаться
при вызове кода интерпретатора. Существует конструктор типа
py_object()
, который создаст указатель PyObject *
. Простое
использование:
import ctypes
d = {}
ctypes.pythonapi.PyObject_SetItem(ctypes.py_object(d),
ctypes.py_object("abc"), ctypes.py_object(1))
# d is now {'abc', 1}.
Не забудьте использовать py_object()
; если он пропущен, вы получить
ошибку сегментации.
ctypes
существует уже некоторое время, но люди все ещё пишут и
распространяют написанные вручную модули расширения, потому что вы не можете
полагаться на присутствие ctypes
. Возможно, разработчики начнут писать
оболочки Python поверх библиотеки, доступ к которой осуществляется через
ctypes
, вместо модулей расширения, теперь, когда ctypes
включён в
ядро Python.
См.также
- http://starship.python.net/crew/theller/ctypes/
- Веб-страница ctypes с учебным пособием, справочником и часто задаваемыми вопросами.
Документация для модуля ctypes
.
Пакет ElementTree¶
Подмножество библиотеки ElementTree Фредрика Лунда для обработки XML было
добавлено в стандартную библиотеку как xml.etree
. Доступные модули:
ElementTree
, ElementPath
и ElementInclude
из ElementTree
1.2.6. Также включён модуль ускорителя cElementTree
.
В оставшейся части этого раздела будет представлен краткий обзор использования ElementTree. Полная документация по ElementTree доступна по адресу http://effbot.org/zone/element-index.htm.
ElementTree представляет XML-документ в виде дерева узлов элементов. Текстовое
содержимое документа хранится в виде атрибутов text
и tail
(это
одно из основных различий между ElementTree и объектной моделью документа; в
DOM существует множество различных типов узлов, включая TextNode
.)
Наиболее часто используемая функция синтаксического анализа — parse()
,
которая принимает либо строку (предположительно содержащую имя файла), либо
файлоподобный объект и возвращает экземпляр ElementTree
:
from xml.etree import ElementTree as ET
tree = ET.parse('ex-1.xml')
feed = urllib.urlopen(
'http://planet.python.org/rss10.xml')
tree = ET.parse(feed)
Получив экземпляр ElementTree
, вы можете вызвать его метод
getroot()
, чтобы получить корневой узел Element
.
Также есть функция XML()
, которая принимает строковый литерал и
возвращает узел Element
(не ElementTree
). Данная функция
обеспечивает аккуратный способ включения фрагментов XML, приближаясь по
удобству к литералу XML:
svg = ET.XML("""<svg width="10px" version="1.0">
</svg>""")
svg.set('height', '320px')
svg.append(elem1)
Каждый элемент XML поддерживает некоторые методы доступа, подобные словарю, и некоторые методы доступа, подобные спискам. Операции, подобные словарю, используются для доступа к значениям атрибутов, а операции, подобные спискам, используются для доступа к дочерним узлам.
Операция | Результа |
---|---|
elem[n] |
Возвращает n-й дочерний элемент. |
elem[m:n] |
Возвращает список дочерних элементов с m-го по n-й. |
len(elem) |
Возвращает количество дочерних элементов. |
list(elem) |
Возвращает список дочерних элементов. |
elem.append(elem2) |
Добавляет elem2 как дочерний. |
elem.insert(index, elem2) |
Вставляет elem2 в указанное место. |
del elem[n] |
Удаляет n-й дочерний элемент. |
elem.keys() |
Возвращает список имён атрибутов. |
elem.get(name) |
Возвращает значение атрибута name. |
elem.set(name, value) |
Задаёт новое значение атрибута name. |
elem.attrib |
Извлекает словарь, содержащий атрибуты. |
del elem.attrib[name] |
Удаляет атрибут name. |
Комментарии и инструкции по обработке также представлены как узлы
Element
. Чтобы проверить, является ли узел комментарием или
оператором по обработке:
if elem.tag is ET.Comment:
...
elif elem.tag is ET.ProcessingInstruction:
...
Чтобы сгенерировать вывод XML, вы должны вызвать метод
ElementTree.write()
. Как и parse()
, он может принимать либо строку,
либо файловый объект:
# Кодировка в US-ASCII
tree.write('output.xml')
# Кодировка - UTF-8
f = open('output.xml', 'w')
tree.write(f, encoding='utf-8')
(Внимание: по умолчанию для вывода используется кодировка ASCII. Для общей работы с XML, когда имя элемента может содержать произвольные символы Юникод, ASCII не очень полезная кодировка, поскольку она вызовет исключение, если имя элемента содержит какие-либо символы со значениями. больше 127. Поэтому лучше указать другую кодировку, такую как UTF-8, которая может обрабатывать любой символ Юникод.)
Данный раздел является лишь частичным описанием интерфейсов ElementTree. Пожалуйста, прочитать официальную документацию пакета для более подробной информации.
См.также
- http://effbot.org/zone/element-index.htm
- Официальная документация для ElementTree.
Пакет hashlib¶
Новый модуль hashlib
, написанный Грегори П. Смитом, был добавлен для
замены модулей md5
и sha
. hashlib
добавляет поддержку
дополнительных безопасных хэшей (SHA-224, SHA-256, SHA-384 и SHA-512). Если
модуль доступен, он использует OpenSSL для быстрой реализации алгоритмов,
оптимизированных для платформы.
Старые модули md5
и sha
все ещё существуют как оболочки вокруг
hashlib для сохранения обратной совместимости. Интерфейс нового модуля очень
близок к интерфейсу старых модулей, но не идентичен. Самое существенное отличие
состоит в том, что функции-конструкторы для создания новых объектов хэширования
называются по-разному.
# Старые версии
h = md5.md5()
h = md5.new()
# Новая версия
h = hashlib.md5()
# Старые версии
h = sha.sha()
h = sha.new()
# Новая версия
h = hashlib.sha1()
# Хэш, которого раньше не было
h = hashlib.sha224()
h = hashlib.sha256()
h = hashlib.sha384()
h = hashlib.sha512()
# Альтернативная форма
h = hashlib.new('md5') # Предоставьте алгоритм в виде строки
После создания хеш-объекта его методы остаются такими же, как и раньше:
update(string)
хэширует указанную строку в текущее состояние дайджеста,
digest()
и hexdigest()
возвращают значение дайджеста в виде
двоичной строки или строки шестнадцатеричных цифр, а copy()
возвращает
новый хэш-объект с тем же состоянием дайджеста.
См.также
Документация для модуля hashlib
.
Пакет sqlite3¶
Модуль pysqlite (http://www.pysqlite.org), оболочка для встроенной базы данных
SQLite, был добавлен в стандартную библиотеку под именем пакета sqlite3
.
SQLite — это библиотека C, которая предоставляет облегченную базу данных на диске, не требующую отдельного серверного процесса и позволяющую обращаться к базе данных с помощью нестандартного варианта языка запросов SQL. Некоторые приложения могут использовать SQLite для внутреннего хранения данных. Также можно создать прототип приложения с помощью SQLite, а затем перенести код в более крупную базу данных, такую как PostgreSQL или Oracle.
pysqlite был написан Герхардом Херингом и предоставляет интерфейс SQL, совместимый со спецификацией DB-API 2.0, описанной в PEP 249.
Если вы компилируете исходный код Python самостоятельно, обратите внимание, что исходное дерево не включает код SQLite, а только модуль-оболочку. Вам нужно будет установить библиотеки и заголовочные файлы SQLite перед компиляцией Python, и процесс сборки скомпилирует модуль, когда будут доступны необходимые заголовочные файлы.
Чтобы использовать модуль, вы должны сначала создать объект
Connection
, представляющий базу данных. Здесь данные будут храниться в
файле /tmp/example
:
conn = sqlite3.connect('/tmp/example')
Вы также можете указать специальное имя :memory:
для создания базы данных в
оперативной памяти.
Получив Connection
, вы можете создать объект Cursor
и вызвать
его метод execute()
для выполнения команд SQL:
c = conn.cursor()
# Создать таблицу
c.execute('''create table stocks
(date text, trans text, symbol text,
qty real, price real)''')
# Вставить строку данных
c.execute("""insert into stocks
values ('2006-01-05','BUY','RHAT',100,35.14)""")
Обычно ваши операции SQL должны использовать значения из переменных Python. Вы не должны собирать свой запрос, используя строковые операции Python, потому что это небезопасно; это делает вашу программу уязвимой для атаки SQL-инъекцией.
Вместо этого используйте подстановку параметров DB-API. Поместите ?
в
качестве заполнителя везде, где вы хотите использовать значение, а затем
указать кортеж значений в качестве второго аргумента для метода курсора
execute()
. (Другие модули базы данных могут использовать другой
заполнитель, например %s
или :1
.) Например:
# Никогда не делайте этого --- небезопасно!
symbol = 'IBM'
c.execute("... where symbol = '%s'" % symbol)
# Сделайте это вместо этого
t = (symbol,)
c.execute('select * from stocks where symbol=?', t)
# Большой пример
for t in (('2006-03-28', 'BUY', 'IBM', 1000, 45.00),
('2006-04-05', 'BUY', 'MSOFT', 1000, 72.00),
('2006-04-06', 'SELL', 'IBM', 500, 53.00),
):
c.execute('insert into stocks values (?,?,?,?,?)', t)
Чтобы получить данные после выполнения инструкции SELECT, вы можете
рассматривать курсор как итератор, вызывать метод курсора fetchone()
для
получения одной совпадающей строки или вызывать fetchall()
для получения
списка совпадающих строк.
В этом примере используется форма итератора:
>>> c = conn.cursor()
>>> c.execute('select * from stocks order by price')
>>> for row in c:
... print row
...
(u'2006-01-05', u'BUY', u'RHAT', 100, 35.140000000000001)
(u'2006-03-28', u'BUY', u'IBM', 1000, 45.0)
(u'2006-04-06', u'SELL', u'IBM', 500, 53.0)
(u'2006-04-05', u'BUY', u'MSOFT', 1000, 72.0)
>>>
Дополнительные сведения о диалекте SQL, поддерживаемом SQLite, см. на странице https://www.sqlite.org.
См.также
- http://www.pysqlite.org
- Веб-страница pysqlite.
- https://www.sqlite.org
- Веб-страница SQLite; документация определяет синтаксис и доступные типы данных для поддерживаемого диалекта SQL.
Документация для модуля sqlite3
.
- PEP 249 — Спецификация API базы данных 2.0
- PEP, написанный Марком-Андре Лембургом.
Пакет wsgiref¶
Интерфейс шлюза веб-сервера (WSGI) версии 1.0 определяет стандартный интерфейс
между веб-серверами и веб-приложениями Python и описан в PEP 333. Пакет
wsgiref
является эталонной реализацией спецификации WSGI.
Пакет включает в себя базовый HTTP-сервер, на котором будет выполняться приложение WSGI; данный сервер полезен для отладки, но не предназначен для использования в производстве. Настройка сервера занимает всего несколько строк кода:
from wsgiref import simple_server
wsgi_app = ...
host = ''
port = 8000
httpd = simple_server.make_server(host, port, wsgi_app)
httpd.serve_forever()
См.также
- http://www.wsgi.org
- Центральный веб-сайт для ресурсов, связанных с WSGI.
- PEP 333 — Интерфейс шлюза веб-сервера Python v1.0
- PEP, написанный Филиппом Дж. Эби.
Изменения сборки и C API¶
Изменения в процессе сборки Python и C API включают в себя:
Исходное дерево Python было преобразовано из CVS в Subversion в ходе сложной процедуры миграции, которую контролировал и безукоризненно выполнил Мартин фон Лёвис. Процедура была разработана как PEP 347.
Компания Coverity, которая продает инструмент для анализа исходного кода Prevent, предоставила результаты исследования исходного кода Python. В ходе анализа было обнаружено около 60 ошибок, которые были оперативно исправлены. Многие из ошибок были связаны с проблемами подсчета ссылок, часто возникающими в коде обработки ошибок. См. https://scan.coverity.com для статистики.
Самое большое изменение в C API произошло от PEP 353, который модифицирует интерпретатор для использования определения типа
Py_ssize_t
вместоint
. Обсуждение этого изменения см. в предыдущем разделе PEP 353: Использование ssize_t в качестве типа индекса.Дизайн компилятора байт-кода сильно изменился, он больше не генерирует байт- код путём обхода дерева синтаксического анализа. Вместо этого дерево синтаксического анализа преобразуется в абстрактное синтаксическое дерево (или AST), и именно абстрактное синтаксическое дерево используется для создания байт-кода.
Код Python может получить объекты AST, используя встроенный
compile()
и указав_ast.PyCF_ONLY_AST
в качестве значения параметра flags:from _ast import PyCF_ONLY_AST ast = compile("""a=0 for i in range(10): a += i """, "<string>", 'exec', PyCF_ONLY_AST) assignment = ast.body[0] for_loop = ast.body[1]
Официальная документация для кода AST ещё не написана, но PEP 339 обсуждает дизайн. Чтобы начать изучение кода, прочитайте определение различных узлов AST в
Parser/Python.asdl
. Сценарий Python читает данный файл и создаёт множество определений структуры C вInclude/Python-ast.h
.PyParser_ASTFromString()
иPyParser_ASTFromFile()
, определённые вInclude/pythonrun.h
, принимают исходный код Python в качестве входных данных и возвращают корень AST, представляющий содержимое. Затем данный AST можно превратить в объект кода с помощьюPyAST_Compile()
. Для получения дополнительной информации прочитайте исходный код, а затем задаёт вопросы на python-dev.Код AST был разработан под руководством Джереми Хилтона и реализован (в алфавитном порядке) Бреттом Кэнноном, Ником Когланом, Грантом Эдвардсом, Джоном Эресманом, Куртом Кайзером, Нилом Норвицем, Тимом Питерсом, Армином Риго и Нилом Шеменауэром, а также участниками ряд спринтов AST на конференциях, таких как PyCon.
Был применен патч Эвана Джонса для obmalloc, впервые описанный в докладе на PyCon DC 2005. Python 2.4 выделял небольшие объекты на аренах размером 256 КБ, но никогда не освобождал арены. С этим патчем Python будет освобождать арены, когда они пусты. Чистый эффект заключается в том, что на некоторых платформах, когда вы выделяете много объектов, использование памяти Python может фактически снизиться при их удалении, и память может быть возвращена операционной системе. (Реализовано Эваном Джонсом и переработано Тимом Питерсом)
Обратите внимание, что это изменение означает, что модули расширения должны быть более осторожными при распределении памяти. API Python имеет множество различных функций для выделения памяти, сгруппированных в семейства. Например,
PyMem_Malloc()
,PyMem_Realloc()
иPyMem_Free()
— это одно семейство, которое выделяет необработанную память, аPyObject_Malloc()
,PyObject_Realloc()
иPyObject_Free()
— другое семейство, которое предполагается использовать для создания объектов Python.Ранее все данные разные семейства сводились к функциям платформы
malloc()
иfree()
. Это означало, что не имело значения, если вы ошиблись и выделили память с помощью функцииPyMem()
, но освободили её с помощью функцииPyObject()
. С изменениями obmalloc в версии 2.5 данные семейства теперь делают разные вещи, и несоответствия, вероятно, приведут к segfault. Вы должны тщательно протестировать свои модули расширения C с помощью Python 2.5.Встроенные типы множеств теперь имеют официальный C API. Вызвать
PySet_New()
иPyFrozenSet_New()
, чтобы создать новый множество,PySet_Add()
иPySet_Discard()
, чтобы добавить и удалить элементы, иPySet_Contains()
иPySet_Size()
, чтобы проверить состояние набора. (Предоставлено Рэймондом Хеттингером.)Код C теперь может получить информацию о точной версии интерпретатора Python, вызвав функцию
Py_GetBuildInfo()
, которая возвращает строку информации о сборке, например:"trunk:45355:45356M, Apr 13 2006, 07:42:19"
. (Предоставлено Барри Варшавой.)Два новых макроса можно использовать для указания функций C, которые являются локальными для текущего файла, чтобы можно было использовать более быстрое соглашение о вызовах.
Py_LOCAL(type)
объявляет функцию как возвращающую значение указанного type и использует квалификатор быстрого вызова.Py_LOCAL_INLINE(type)
делает то же самое и также запрашивает встраивание функции. ЕслиPY_LOCAL_AGGRESSIVE()
определён до включенияpython.h
, для модуля включается множество более агрессивных оптимизаций; вам следует сравнить результаты, чтобы выяснить, действительно ли данные оптимизации делают код быстрее. (Предоставил Фредрик Лунд на спринте NeedForSpeed.PyErr_NewException(name, base, dict)
теперь может принимать кортеж базовых классов в качестве аргумента base. (Предоставлено Георгом Брандлом)Функция
PyErr_Warn()
для выдачи предупреждений теперь устарела в пользуPyErr_WarnEx(category, message, stacklevel)
, которая позволяет указать количество фреймов стека, разделяющих эту функцию и вызывающую программу. stacklevel, равный 1, — это функция, вызывающаяPyErr_WarnEx()
, 2 — это функция над ней и так далее. (Добавлено Нилом Норвицем)Интерпретатор CPython по-прежнему написан на C, но код теперь можно компилировать с помощью компилятора C++ без ошибок. (Реализовано Энтони Бакстером, Мартином фон Лёвисом, Скипом Монтанаро)
Функция
PyRange_New()
удалена. Он никогда не был задокументирован, никогда не использовался в основном коде и имел опасно слабую проверку ошибок. В маловероятном случае, если ваши расширения использовали его, вы можете заменить его чем-то вроде следующего:range = PyObject_CallFunction((PyObject*) &PyRange_Type, "lll", start, stop, step);
Изменения для портов¶
- MacOS X (10.3 и выше): динамическая загрузка модулей теперь использует
функцию
dlopen()
вместо функций, специфичных для MacOS. - MacOS X: в скрипт configure добавлен переключатель
-- enable-universalsdk
, который компилирует интерпретатор как универсальный двоичный файл, способный работать как на процессорах PowerPC, так и на процессорах Intel. (Предоставлено Рональдом Уссореном; bpo-2573.) - Windows:
.dll
больше не поддерживается в качестве расширения имени файла для модулей расширения..pyd
теперь единственное расширение имени файла, которое будет искаться.
Портирование на Python 2.5¶
В этом разделе перечислены ранее описанные изменения, которые могут потребовать внесения изменений в ваш код:
- ASCII теперь является кодировкой по умолчанию для модулей. Теперь это синтаксическая ошибка, если модуль содержит строковые литералы с 8-битными символами, но не имеет объявления кодировки. В Python 2.4 это вызвало предупреждение, а не синтаксическую ошибку.
- Ранее атрибут генератора
gi_frame
всегда был объектом фрейма. Из-за изменений PEP 342, описанных в разделе PEP 342: Новые функции генератора, теперьgi_frame
может бытьNone
. - Новое предупреждение
UnicodeWarning
выдается при попытке сравнить строку Юникод и 8-битную строку, которую нельзя преобразовать в Юникод с использованием кодировки ASCII по умолчанию. Раньше такие сравнения вызывали исключениеUnicodeDecodeError
. - Библиотека: модуль
csv
теперь более строго относится к многострочным полям в кавычках. Если ваши файлы содержат новые строки, встроенные в поля, ввод должен быть разбит на строки таким образом, чтобы сохранить символы новой строки. - Библиотека: функция
format()
модуляlocale
ранее принимала любую строку, если появлялось не более одного спецификатора %char. В Python 2.5 аргумент должен быть ровно одним спецификатором %char без окружающего текста. - Библиотека: модули
pickle
иcPickle
больше не принимают возвращаемое значениеNone
из метода__reduce__()
; вместо этого метод должен возвращать кортеж аргументов. Модули также больше не принимают устаревший ключевой параметр bin. - Библиотека: классы
SimpleXMLRPCServer
иDocXMLRPCServer
теперь имеют атрибутrpc_paths
, ограничивающий операции XML-RPC ограниченным набором URL-адресов; по умолчанию разрешены только'/'
и'/RPC2'
. Установкаrpc_paths
вNone
или пустой кортеж отключает эту проверку пути. - C API: многие функции теперь используют
Py_ssize_t
вместоint
, что позволяет обрабатывать больше данных на 64-разрядных машинах. В коде расширения может потребоваться внести такое же изменение, чтобы избежать предупреждений и обеспечить поддержку 64-разрядных машин. Обсуждение этого изменения см. в предыдущем разделе PEP 353: Использование ssize_t в качестве типа индекса. - C API: изменения obmalloc означают, что вы должны быть осторожны, чтобы не
смешивать использование семейств функций
PyMem_*()
иPyObject_*()
. Память, выделенная с помощью*_Malloc()
одного семейства, должна быть освобождена с помощью функции*_Free()
соответствующего семейства.
Благодарности¶
Автор хотел бы поблагодарить следующих людей за предложения, исправления и помощь с различными черновиками этой статьи: Георга Брандла, Ника Коглана, Филиппа Дж. Эби, Ларса Густебеля, Рэймонда Хеттингера, Ральфа В. Гроссе- Кунстлеве, Кента Джонсона, Иэн Лоу, Мартин фон Лёвис, Фредрик Лунд, Эндрю Макнамара, Скип Монтанаро, Густаво Нимейер, Пол Прескод, Джеймс Прайор, Майк Ровнер, Скотт Вайкарт, Барри Уоршан, Томас Воутерс.