Содержание страницы
Что нового в Python 2.5¶What’s New in Python 2.5
| Автор: | A.M. Kuchling |
|---|
В этой статье объясняются новые возможности Python 2.5. Выпуск финальной версии Python 2.5 запланирован на август 2006 года; в PEP 356 описан планируемый график выпуска.
Изменения в Python 2.5 представляют собой интересное сочетание улучшений языка и библиотек. Улучшения библиотек будут важнее для сообщества Python, поскольку было добавлено несколько широко используемых пакетов. Новые модули включают ElementTree для обработки XML (xml.etree), модуль базы данных SQLite (sqlite) и модуль ctypes для вызова функций C.
Изменения в языке имеют среднюю значимость. Были добавлены некоторые приятные новые возможности, но большинство из них не являются функциями, которыми вы будете пользоваться каждый день. Условные выражения наконец-то были добавлены в язык с использованием нового синтаксиса; см. раздел PEP 308: Conditional Expressions. Новый оператор with упростит написание кода очистки (раздел PEP 343: The ‘with’ statement). Теперь в генераторы можно передавать значения (раздел PEP 342: New Generator Features). Импорты теперь могут быть абсолютными или относительными (раздел PEP 328: Absolute and Relative Imports). Некоторые граничные случаи обработки исключений обрабатываются лучше (раздел PEP 341: Unified try/except/finally). Все эти улучшения стоят того, но они касаются отдельных языковых возможностей; ни одно из них не является широкими изменениями семантики Python.
Помимо дополнений в языке и библиотеке, по всему дереву исходного кода были внесены другие улучшения и исправления ошибок. Поиск по журналам изменений SVN показывает, что между Python 2.4 и 2.5 было применено 353 патча и исправлено 458 ошибок. (Обе цифры, вероятно, занижены.)
Эта статья не претендует на полное описание новых возможностей; вместо этого изменения кратко представлены с помощью наглядных примеров. Для полных подробностей всегда следует обращаться к документации Python 2.5 по адресу http://docs.python.org. Если вы хотите понять полную реализацию и обоснование проекта, обратитесь к PEP для конкретной новой возможности.
Комментарии, предложения и сообщения об ошибках по этому документу приветствуются; пожалуйста, отправляйте их автору по электронной почте или открывайте ошибку в трекере ошибок Python.
PEP 308: Условные выражения¶PEP 308: Conditional Expressions
Долгое время люди просили способ писать условные выражения, то есть выражения, которые возвращают значение 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», «if logging», «else 0» и подумать, что условие определяет, выполняется ли присваивание level. Вторая версия читается лучше, на мой взгляд, потому что она ясно показывает, что присваивание выполняется всегда, а выбор делается между двумя значениями.
Еще одна причина для включения скобок: несколько странных комбинаций списковых включений и лямбда-функций могут выглядеть как некорректные условные выражения. См. PEP 308 для некоторых примеров. Если вы ставите скобки вокруг своих условных выражений, вы не столкнетесь с этой ситуацией.
См. также
- PEP 308 – Условные выражения
- PEP написан Гвидо ван Россумом и Раймондом Д. Хеттингером; реализован Томасом Воутерсом.
PEP 309: Частичное применение функций¶PEP 309: Partial Function Application
Модуль 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):
"Write the contents of 'message' to the specified subsystem."
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() копирует имя, модуль и атрибут 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¶PEP 314: Metadata for Python Software Packages 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 по адресу http://cheeseshop.python.org – это хранение исходных и бинарных архивов для пакета. Новая команда upload Distutils будет загружать пакет в репозиторий.
Прежде чем пакет можно будет загрузить, необходимо уметь собирать дистрибутив с помощью команды Distutils sdist. Когда это работает, можно запустить python setup.py upload, чтобы добавить пакет в архив PyPI. При желании можно подписать пакет GPG, указав параметры --sign и --identity.
Загрузка пакетов была реализована Мартином фон Лёвисом и Ричардом Джонсом.
См. также
- PEP 314 – Метаданные для пакетов программного обеспечения Python v1.1
- PEP предложен и написан А.М. Кухлингом, Ричардом Джонсом и Фредом Дрейком; реализован Ричардом Джонсом и Фредом Дрейком.
PEP 328: Абсолютный и относительный импорт¶PEP 328: Absolute and Relative Imports
Более простая часть 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 – это то, что нужно. Но что если нужен стандартный модуль string Python? Чистого способа игнорировать pkg.string и искать стандартный модуль не было; обычно приходилось смотреть содержимое sys.modules, что слегка нечисто. Пакет py.std Хольгера Крекеля предоставляет более аккуратный способ импорта из стандартной библиотеки, 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 написан Aahz; реализован Томасом Ваутерсом.
- http://codespeak.net/py/current/doc/index.html
- Библиотека py от Holger Krekel, которая содержит пакет py.std.
PEP 338: Выполнение модулей как сценариев¶PEP 338: Executing Modules as Scripts
Ключ -m, добавленный в Python 2.4 для выполнения модуля как скрипта, приобрёл несколько новых возможностей. Вместо реализации на C внутри интерпретатора Python, ключ теперь использует реализацию в новом модуле runpy.
Модуль runpy реализует более сложный механизм импорта, так что теперь можно запускать модули в пакете, например pychecker.checker. Модуль также поддерживает альтернативные механизмы импорта, такие как модуль zipimport. Это означает, что можно добавить путь к .zip-архиву в sys.path, а затем использовать ключ -m для выполнения кода из архива.
См. также
- PEP 338 – Выполнение модулей как сценариев
- PEP написан и реализован Ником Когленом.
PEP 341: Унифицированный try/except/finally¶PEP 341: Unified 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.
Независимо от того, что произошло ранее, блок finally выполняется после завершения блока кода и обработки всех возникших исключений. Даже если в обработчике исключения или в блоке else произошла ошибка и возникло новое исключение, код в блоке finally всё равно выполняется.
См. также
- PEP 341 – Объединение try-except и try-finally
- Автор PEP – Georg Brandl; реализация – Thomas Lee.
PEP 342: Новые возможности генераторов¶PEP 342: New Generator Features
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)
# Если передано значение, изменить counter.
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 генератора всегда был объектом frame. Теперь возможно, что gi_frame будет равен None после исчерпания генератора.
См. также
- PEP 342 - Coroutines via Enhanced Generators
Авторы PEP – Guido van Rossum и Phillip J. Eby; реализация – Phillip J. Eby. Включает примеры более изощрённого использования генераторов в качестве корутин.
Более ранние версии этих возможностей были предложены в PEP 288 Рэймондом Хеттингером и в PEP 325 Самуэле Педрони.
- http://en.wikipedia.org/wiki/Coroutine
- Статья в Википедии о корутинах.
- http://www.sidhe.org/~dan/blog/archives/000178.html
- Объяснение корутин с точки зрения Perl, написано Дэном Сугальски.
PEP 343: Оператор ‘with’¶PEP 343: The ‘with’ statement
Инструкция ‘with‘ делает код понятнее: ранее для гарантии выполнения кода очистки приходилось использовать блоки try...finally. В этом разделе я расскажу о том, как обычно используется эта инструкция. В следующем разделе я рассмотрю детали реализации и покажу, как создавать объекты для работы с этой инструкцией.
Инструкция ‘with‘ – это новая управляющая конструкция, базовая структура которой выглядит так:
with expression [as variable]:
with-block
Выражение вычисляется и должно дать объект, поддерживающий протокол управления контекстом (то есть имеющий методы __enter__() и __exit__()).
Метод __enter__() объекта вызывается до выполнения блока with и, следовательно, может выполнить код настройки. Он также может возвращать значение, которое при наличии переменной привязывается к этому имени. (Обратите внимание: variable – это не результат вычисления expression.)
После завершения выполнения блока with вызывается метод __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
... more processing code ...
После выполнения этой инструкции файловый объект f будет автоматически закрыт, даже если цикл for возбудил исключение где-то посередине блока.
Примечание
В этом случае f – это тот же объект, созданный open(), поскольку file.__enter__() возвращает self.
Блокировки и переменные условия модуля threading также поддерживают инструкцию ‘with‘:
lock = threading.Lock()
with lock:
# Критическая секция кода
...
Блокировка захватывается перед выполнением блока и всегда освобождается после завершения блока.
Новая функция localcontext() в модуле decimal упрощает сохранение и восстановление текущего контекста decimal, который инкапсулирует желаемую точность и правила округления для вычислений:
from decimal import Decimal, Context, localcontext
# Отображается с точностью по умолчанию в 28 знаков
v = Decimal('578')
print v.sqrt()
with localcontext(Context(prec=16)):
# Весь код в этом блоке использует точность в 16 знаков.
# Исходный контекст восстанавливается при выходе из блока.
print v.sqrt()
Написание контекстных менеджеров¶Writing Context Managers
Внутреннее устройство инструкции ‘with‘ довольно сложное. Большинство людей будут использовать ‘with‘ только вместе с существующими объектами и не нуждаются в знании этих деталей, поэтому можно пропустить остальную часть этого раздела, если захочется. Авторам новых объектов потребуется разобраться в деталях реализации и стоит продолжить чтение.
Объяснение протокола управления контекстом на высоком уровне:
- Выражение вычисляется и должно дать объект, называемый «менеджер контекста». Менеджер контекста должен иметь методы __enter__() и __exit__().
- Вызывается метод __enter__() менеджера контекста. Возвращённое значение присваивается VAR. Если предложение 'as VAR' отсутствует, значение просто отбрасывается.
- Код внутри блока выполняется.
- Если в блоке BLOCK возникает исключение, вызывается метод __exit__(type, value, traceback)() с деталями исключения – теми же значениями, которые возвращает sys.exc_info(). Возвращаемое значение метода определяет, будет ли исключение проброшено заново: любое ложное значение приводит к повторному возбуждению, а True – к его подавлению. Подавлять исключение нужно лишь в редких случаях, поскольку если это сделать, автор кода, содержащего оператор ‘with‘, никогда не узнает, что что-то пошло не так.
- Если BLOCK не возбудил исключение, метод __exit__() всё равно вызывается, но type, value и traceback равны None.
Рассмотрим пример. Мы не будем приводить подробный код, а лишь в общих чертах опишем методы, необходимые для базы данных, поддерживающей транзакции.
(Для тех, кто не знаком с терминологией баз данных: набор изменений в базе данных группируется в транзакцию. Транзакции могут быть либо зафиксированы (committed) – это означает, что все изменения записаны в базу данных, либо откачены (rolled back) – что означает, что все изменения отменены, а база данных не изменена. За дополнительной информацией обращайтесь к любому учебнику по базам данных.)
Предположим, что существует объект, представляющий подключение к базе данных. Наша цель – позволить пользователю написать такой код:
db_connection = DatabaseConnection()
with db_connection as cursor:
cursor.execute('insert into ...')
cursor.execute('delete from ...')
# ... дополнительные операции ...
Транзакция должна быть зафиксирована, если код в блоке выполняется без ошибок, или откатана при возникновении исключения. Вот базовый интерфейс для DatabaseConnection, который я буду предполагать:
class DatabaseConnection:
# Интерфейс базы данных
def cursor (self):
"Returns a cursor object and starts a new transaction"
def commit (self):
"Commits current transaction"
def rollback (self):
"Rolls back current transaction"
Метод __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 ¶The contextlib module
В новом модуле contextlib появились функции и декоратор, полезные для написания объектов, используемых с оператором ‘with‘.
Декоратор называется contextmanager() и позволяет написать одну функцию-генератор вместо определения нового класса. Генератор должен выдать ровно одно значение. Код до yield выполняется как метод __enter__(), а возвращаемое значение yield становится значением, которое будет связано с переменной в предложении 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 написан Гвидо ван Россумом и Ником Когланом; реализован Майком Блэндом, Гвидо ван Россумом и Нилом Норвицем. В PEP показан код, генерируемый для оператора ‘with‘, что может быть полезно для понимания его работы.
Документация к модулю contextlib.
PEP 352: Исключения как классы нового стиля¶PEP 352: Exceptions as New-Style Classes
Классы исключений теперь могут быть классами нового стиля, а не только классическими, и встроенный класс Exception, а также все стандартные встроенные исключения (NameError, ValueError и т.д.) теперь являются классами нового стиля.
Иерархия наследования для исключений была немного перестроена. В версии 2.5 отношения наследования таковы:
BaseException # Новое в Python 2.5
|- KeyboardInterrupt
|- SystemExit
|- Exception
|- (all other current built-in exceptions)
Это изменение было сделано потому, что люди часто хотят перехватывать все исключения, указывающие на ошибки программы. Однако 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 в качестве типа индекса¶PEP 353: Using ssize_t as the index type
Масштабное изменение C API Python: вместо int теперь используется новый тип Py_ssize_t, что позволит интерпретатору обрабатывать больше данных на 64-битных платформах. Это изменение не влияет на ёмкость Python на 32-битных платформах.
Различные части интерпретатора Python использовали тип int в C для хранения размеров или количества; например, количество элементов в списке или кортеже хранилось в int. Компиляторы C для большинства 64-битных платформ по-прежнему определяют int как 32-битный тип, поэтому списки могли содержать не более 2**31 - 1 = 2147483647 элементов. (На самом деле существует несколько моделей программирования, используемых 64-битными компиляторами C – см. http://www.unix.org/version2/whatsnew/lp64_wp.html для обсуждения – но наиболее распространённая модель оставляет int 32-битным.)
Ограничение в 2147483647 элементов не имеет значения на 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__’¶PEP 357: The ‘__index__’ method
У разработчиков NumPy была проблема, которую можно было решить только добавлением нового специального метода __index__(). При использовании срезов, например [start:stop:step], значения индексов start, stop и step должны быть целыми числами (int или long). NumPy определяет множество специализированных целочисленных типов, соответствующих беззнаковым и знаковым целым 8, 16, 32 и 64 бит, но не было способа указать, что эти типы можно использовать в качестве индексов среза.
Для срезов нельзя просто использовать существующий метод __int__(), потому что он также используется для приведения к целым числам. Если бы срезы использовали __int__(), числа с плавающей запятой тоже стали бы допустимыми индексами срезов, а это явно нежелательное поведение.
Вместо этого был добавлен новый специальный метод __index__(). Он не принимает аргументов и возвращает целое число, которое будет использоваться как индекс среза. Например:
class C:
def __index__ (self):
return self.value
Возвращаемое значение должно быть Python-целым (int или long). Интерпретатор проверит, что тип возвращаемого значения корректен, и возбудит TypeError, если это требование не выполняется.
Соответствующий слот nb_index был добавлен в C-структуру PyNumberMethods, чтобы расширения на C могли реализовать этот протокол. PyNumber_Index(obj)() может использоваться в коде расширений для вызова функции __index__() и получения её результата.
См. также
- PEP 357 – Разрешение использования любого объекта для срезов
- Автор и разработчик PEP – Трэвис Олифант.
Прочие изменения языка ¶Other Language Changes
Ниже перечислены все изменения, которые 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] # Выводит 1, 2 print d[3], d[4] # Выводит 0, 0
Как 8-битные, так и строки Unicode получили новые методы partition(sep)() и rpartition(sep)(), которые упрощают типичный сценарий использования.
Метод find(S)() часто используется для получения индекса, который затем применяется, чтобы извлечь части строки до и после разделителя. partition(sep)() объединяет этот шаблон в один вызов метода, который возвращает кортеж из трёх элементов: подстроку до разделителя, сам разделитель и подстроку после разделителя. Если разделитель не найден, первый элемент кортежа – вся строка, а остальные два – пусты. rpartition(sep)() также возвращает кортеж из трёх элементов, но начинает поиск с конца строки; r означает «reverse» (обратный).
Несколько примеров:
>>> ('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__() класса теперь может быть как длинным целым (long), так и обычным. Если возвращается длинное целое, берётся хэш этого значения. В более ранних версиях хэш должен был быть обычным целым, но в 2.5 встроенная функция id() была изменена так, чтобы всегда возвращать неотрицательные числа, и пользователи часто используют id(self) в методах __hash__() (хотя это не рекомендуется).
Теперь ASCII является кодировкой по умолчанию для модулей. Если модуль содержит строковые литералы с 8-битными символами, но не имеет декларации кодировки, это теперь синтаксическая ошибка. В Python 2.4 это вызывало предупреждение, а не синтаксическую ошибку. См. PEP 263 для получения информации о том, как объявить кодировку модуля; например, можно добавить строку в верхней части исходного файла:
# -*- coding: latin1 -*-Новое предупреждение UnicodeWarning возникает при попытке сравнить Unicode-строку и 8-битную строку, которую невозможно преобразовать в Unicode с помощью кодировки ASCII по умолчанию. Результат сравнения – ложь:
>>> chr(128) == unichr(128) # Не удаётся преобразовать chr(128) в Unicode __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 при импорте, который мог бы воспринять каталог как пакет, но не обнаружил __init__.py, теперь генерируется новое предупреждение ImportWarning. Это предупреждение по умолчанию игнорируется; чтобы его увидеть, укажите параметр -Wd при запуске исполняемого файла Python. (Реализовано Томасом Воутерсом.)
Список базовых классов в определении класса теперь может быть пустым. Например, теперь это допустимо:
class C(): pass
(Реализовано Бреттом Кэнноном.)
Изменения в интерактивном интерпретаторе¶Interactive Interpreter Changes
В интерактивном интерпретаторе quit и exit долгое время были строками, чтобы новые пользователи получали более-менее полезное сообщение при попытке выйти:
>>> quit
'Use Ctrl-D (i.e. EOF) to exit.'
В Python 2.5 quit и exit теперь являются объектами, которые по-прежнему возвращают строковое представление самих себя, но также могут быть вызваны. Новички, попробовавшие quit() или exit(), теперь выйдут из интерпретатора, как они и ожидали. (Реализовано Георгом Брандлом.)
Исполняемый файл Python теперь принимает стандартные длинные параметры --help и --version; в Windows он также принимает параметр /? для отображения справочного сообщения. (Реализовано Георгом Брандлом.)
Оптимизации¶Optimizations
Некоторые из оптимизаций были разработаны на спринте NeedForSpeed, проходившем в Рейкьявике, Исландия, с 21 по 28 мая 2006 года. Спринт был посвящен повышению производительности реализации CPython и финансировался компанией EWT LLC при локальной поддержке CCP Games. Оптимизации, добавленные на этом спринте, отмечены особым образом в следующем списке.
- Когда в Python 2.4 были введены встроенные типы set и frozenset, они были реализованы поверх словаря Python. В версии 2.5 внутренняя структура данных была адаптирована для реализации множеств, и в результате множества будут потреблять на треть меньше памяти и работать несколько быстрее. (Реализовано Рэймондом Хеттингером.)
- Скорость некоторых операций с Unicode, таких как поиск подстрок, разделение строк, а также кодирование и декодирование с помощью символьных карт, была повышена. (Улучшения поиска подстрок и разделения строк были добавлены Фредриком Лундом и Эндрю Далком на спринте NeedForSpeed. Символьные карты улучшены Вальтером Дёрвальдом и Мартином фон Лёвисом.)
- Функция long(str, base)() теперь работает быстрее на длинных строковых представлениях чисел, так как вычисляется меньше промежуточных результатов. Пик производительности достигается на строках длиной около 800–1000 цифр, где функция работает в 6 раз быстрее. (Автор: Alan McIntyre, принято на спринте 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. (Предложено и реализовано Рэймондом Хеттингером.)
- Вызовы функций теперь выполняются быстрее, поскольку объекты кода теперь хранят последний завершенный фрейм ("zombie frame") во внутреннем поле объекта кода и повторно используют его при следующем вызове. (Оригинальный патч Майкла Хадсона, модифицирован Армином Риго и Ричардом Джонсом; добавлен на спринте NeedForSpeed.) Объекты фреймов также стали немного меньше, что может улучшить локальность кэша и немного уменьшить потребление памяти. (Автор: Нил Норвиц.)
- Встроенные исключения Python теперь являются классами нового стиля, что значительно ускоряет их создание. Обработка исключений в Python 2.5 выполняется примерно на 30% быстрее, чем в 2.4. (Авторы: Ричард Джонс, Георг Брандль и Шон Райфшнайдер на спринте NeedForSpeed.)
- При импорте теперь кешируются проверенные пути с записью, существуют они или нет, что позволяет интерпретатору выполнять меньше вызовов open() и stat() при запуске. (Предложено Мартином фон Лёвисом и Георгом Брандлом.)
Новые, улучшенные и удаленные модули¶New, Improved, and Removed Modules
Стандартная библиотека получила множество улучшений и исправлений ошибок в 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']}
(Автор: Guido van Rossum.)
Тип deque (двусторонняя очередь), предоставляемый модулем collections, теперь имеет метод remove(value)(), который удаляет первое вхождение value в очереди, возбуждая ValueError, если значение не найдено. (Автор: Raymond Hettinger.)
Новый модуль: модуль contextlib содержит вспомогательные функции для использования с новым оператором ‘with’. См. раздел Модуль contextlib для получения дополнительной информации об этом модуле.
Новый модуль: модуль cProfile – это реализация на C существующего модуля profile с гораздо меньшими накладными расходами. Интерфейс модуля такой же, как у profile: можно запустить cProfile.run('main()') для профилирования функции, сохранить данные профиля в файл и т.д. Пока не известно, будет ли профайлер Hotshot, который тоже написан на C, но не соответствует интерфейсу модуля profile, поддерживаться в будущих версиях Python. (Предложено Армином Риго.)
Кроме того, модуль pstats для анализа данных, измеренных профайлером, теперь поддерживает направление вывода в любой файловый объект с помощью аргумента поток данных, передаваемого конструктору Stats. (Предложено Скипом Монтанаро.)
Модуль csv, который разбирает файлы в формате CSV (значения, разделённые запятыми), получил несколько улучшений и ряд исправлений ошибок. Теперь можно задать максимальный размер поля в байтах, вызвав функцию csv.field_size_limit(new_limit)(); опускание аргумента new_limit возвращает текущий лимит. Класс reader теперь имеет атрибут line_num, который подсчитывает количество физических строк, прочитанных из источника; записи могут занимать несколько физических строк, поэтому line_num не совпадает с количеством прочитанных записей.
Парсер CSV теперь более строг в отношении многострочных полей в кавычках. Ранее, если строка заканчивалась внутри поля в кавычках без завершающего символа новой строки, в возвращаемое поле вставлялся символ новой строки. Такое поведение вызывало проблемы при чтении файлов, содержащих символы возврата каретки внутри полей, поэтому код был изменён для возврата поля без вставки символов новой строки. Как следствие, если символы новой строки внутри полей важны, входные данные следует разбивать на строки таким образом, чтобы эти символы сохранялись.
(Авторы: Skip Montanaro и Andrew McNamara.)
Класс datetime в модуле datetime теперь имеет метод strptime(string, format)() для разбора строк с датами, предоставленный Джошем Споэрри (Josh Spoerri). Он использует те же форматные символы, что и 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 стал более гибким. Теперь поддерживаются имена файлов в Unicode, а в функцию input() добавлен параметр mode со значением по умолчанию "r" для открытия файлов в бинарном режиме или режиме универсальных новых строк. Ещё один новый параметр, 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']
(Автор: Raymond Hettinger.)
Функция itertools.islice() теперь принимает None для аргументов start и step. Это делает её более совместимой с атрибутами объектов slice, так что теперь можно написать следующее:
s = slice(5) # Создать объект среза itertools.islice(iterable, s.start, s.stop, s.step)
(Автор: Raymond Hettinger.)
Функция format() в модуле locale была изменена, и добавлены две новые функции: format_string() и currency().
Ранее параметр val функции format() мог быть строкой, если в ней содержался не более одного спецификатора %char; теперь параметр должен быть ровно одним спецификатором %char без окружающего текста. Также добавлен необязательный параметр monetary, который, если установлен в True, будет использовать правила локали для форматирования валюты при размещении разделителя между группами из трёх цифр.
Для форматирования строк с несколькими спецификаторами %char используйте новую функцию format_string(), которая работает как format(), но также поддерживает смешивание спецификаторов %char с произвольным текстом.
Также была добавлена новая функция currency(), которая форматирует число в соответствии с настройками текущей локали.
(Автор: Georg Brandl.)
Модуль 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)
(Автор: Gregory K. Johnson. Финансирование предоставлено программой Google Summer of Code 2005.)
Новый модуль: модуль msilib позволяет создавать файлы установщика Microsoft .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 теперь по умолчанию имеет значение true, что означает, что 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() не принимает идентификатор процесса, поэтому ожидает завершения любого дочернего процесса и возвращает кортеж из трёх элементов: идентификатор процесса, код завершения, использование ресурсов, возвращаемые функцией resource.getrusage(). wait4(pid)() принимает идентификатор процесса. (Автор: Chad J. Schroeder.)
На 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, благодаря патчу от Филиппа Бионди. Сокеты Netlink – это Linux-специфичный механизм для взаимодействия между процессом пользовательского пространства и кодом ядра; вводная статья о них находится по адресу http://www.linuxjournal.com/article/7356. В коде Python адреса netlink представляются в виде кортежа из двух целых чисел: (pid, group_mask).
Два новых метода у объектов сокетов, recv_into(buffer)() и recvfrom_into(buffer)(), сохраняют полученные данные в объект, который поддерживает буферный протокол, вместо возврата данных в виде строки. Это означает, что данные можно помещать непосредственно в массив или файл, отображённый в память.
Объекты сокетов также получили методы доступа 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|*'. (Автор: Lars Gustäbel.)
Модуль threading теперь позволяет задавать размер стека, используемый при создании новых потоков. Функция stack_size([*size*])() возвращает текущий размер стека, а передача необязательного параметра size устанавливает новое значение. Не все платформы поддерживают изменение размера стека, но Windows, POSIX-потоки и OS/2 – да. (Автор: Andrew MacIntyre.)
Модуль unicodedata обновлён для использования версии 4.1.0 базы данных символов Unicode. Версия 3.2.0 требуется некоторыми спецификациями, поэтому она всё ещё доступна как unicodedata.ucd_3_2_0.
Новый модуль: модуль uuid генерирует универсальные уникальные идентификаторы (UUID) в соответствии с RFC 4122. В RFC определено несколько различных версий UUID, которые генерируются из начальной строки, из системных свойств или чисто случайным образом. Этот модуль содержит класс UUID и функции с именами uuid1(), uuid3(), uuid4() и uuid5() для генерации различных версий UUID. (Версия 2 UUID не указана в 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')
(Автор: Ka-Ping Yee.)
Типы WeakKeyDictionary и WeakValueDictionary модуля weakref получили новые методы для итерации по слабым ссылкам, содержащимся в словаре. Методы iterkeyrefs() и keyrefs() были добавлены в WeakKeyDictionary, а itervaluerefs() и valuerefs() – в WeakValueDictionary. (Автор: Fred L. Drake, Jr.)
Модуль 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, чтобы включить эту возможность. (Автор: Skip Montanaro.)
Модуль zipfile теперь поддерживает формат ZIP64, что означает, что .zip-архив может быть больше 4 GiB и содержать отдельные файлы размером более 4 GiB. (Автор: Ronald Oussoren.)
Объекты Compress и Decompress модуля zlib теперь поддерживают метод copy(), который создаёт копию внутреннего состояния объекта и возвращает новый объект Compress или Decompress. (Автор: Chris AtLee.)
Пакет ctypes¶The ctypes package
Пакет 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, но для других типов необходимо вызывать правильный конструктор типов. (И я имею в виду необходимо; ошибка часто приводит к аварийному завершению интерпретатора с ошибкой сегментации.)
Не следует использовать 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 также предоставляет обёртку для C API Python в виде объекта ctypes.pythonapi. Этот объект не освобождает глобальную блокировку интерпретатора перед вызовом функции, поскольку блокировка должна удерживаться при вызове кода интерпретатора. Имеется конструктор типа py_object(), который создаёт указатель PyObject *. Простой пример использования:
import ctypes
d = {}
ctypes.pythonapi.PyObject_SetItem(ctypes.py_object(d),
ctypes.py_object("abc"), ctypes.py_object(1))
# d теперь содержит {'abc', 1}.
Не забывайте использовать py_object(); если его опустить, результатом будет ошибка сегментации.
ctypes существует уже некоторое время, но люди всё ещё пишут и распространяют написанные вручную модули расширения, поскольку нельзя полагаться на наличие ctypes. Возможно, теперь, когда ctypes включён в ядро Python, разработчики начнут писать обёртки Python на основе библиотек, доступ к которым осуществляется через ctypes, вместо модулей расширения.
См. также
- http://starship.python.net/crew/theller/ctypes/
- Веб-страница ctypes с учебным пособием, справочником и часто задаваемыми вопросами.
Документация модуля ctypes.
Пакет ElementTree¶The ElementTree package
Подмножество библиотеки 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); в 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, где имя элемента может содержать произвольные символы Unicode, ASCII – не очень полезная кодировка, так как она вызовет исключение, если имя элемента содержит символы со значениями больше 127. Поэтому лучше указать другую кодировку, например UTF-8, которая может обрабатывать любые символы Unicode.)
Этот раздел содержит лишь частичное описание интерфейсов ElementTree. Пожалуйста, прочитайте официальную документацию пакета для получения более подробной информации.
См. также
- http://effbot.org/zone/element-index.htm
- Официальная документация для ElementTree.
Пакет hashlib¶The hashlib package
Новый модуль hashlib, написанный Gregory P. Smith, был добавлен для замены модулей 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') # Указать алгоритм в виде строки
После создания хэш-объекта его методы остаются прежними:\nupdate(string)() хэширует указанную строку в текущее состояние\nдайджеста, digest() и hexdigest() возвращают значение дайджеста в виде двоичной\nстроки или строки шестнадцатеричных цифр, а copy() возвращает новый хэширующий объект\nс тем же состоянием дайджеста.
См. также
Документация для модуля hashlib.
Пакет sqlite3¶The sqlite3 package
Модуль pysqlite (http://www.pysqlite.org), обёртка для встраиваемой базы данных SQLite, был добавлен в стандартную библиотеку под именем пакета sqlite3.
SQLite – это библиотека на C, которая предоставляет легковесную дисковую базу данных, не требующую отдельного серверного процесса, и позволяет обращаться к базе данных с помощью нестандартного варианта языка SQL. Некоторые приложения могут использовать SQLite для внутреннего хранения данных. Также можно создать прототип приложения на SQLite, а затем перенести код на более крупную базу данных, например PostgreSQL или Oracle.
pysqlite был написан Gerhard Häring и предоставляет 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, см. http://www.sqlite.org.
См. также
- http://www.pysqlite.org
- Веб-страница pysqlite.
- http://www.sqlite.org
- Веб-страница SQLite; документация описывает синтаксис и доступные типы данных для поддерживаемого диалекта SQL.
Документация для модуля sqlite3.
- PEP 249 – спецификация API баз данных 2.0
- PEP написан Марком-Андре Лембургом.
Пакет wsgiref¶The wsgiref package
Интерфейс шлюза веб-сервера (WSGI) v1.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¶Build and C API Changes
Изменения процесса сборки Python и C API включают:
Дерево исходного кода Python было перенесено из CVS в Subversion в ходе сложной процедуры миграции, которую курировал и безупречно выполнил Martin von Löwis. Эта процедура была разработана как PEP 347.
Компания Coverity, продающая инструмент анализа исходного кода Prevent, предоставила результаты проверки исходного кода Python. Анализ выявил около 60 ошибок, которые были быстро исправлены. Многие ошибки были связаны с подсчётом ссылок (refcounting) и часто возникали в коде обработки ошибок. Статистику см. на http://scan.coverity.com.
Самое большое изменение в C API произошло из-за PEP 353, который изменяет интерпретатор, чтобы использовать определение типа Py_ssize_t вместо int. См. выше раздел PEP 353: Использование ssize_t в качестве типа индекса для обсуждения этого изменения.
Конструкция компилятора байт-кода сильно изменилась: он больше не генерирует байт-код обходом дерева разбора. Вместо этого дерево разбора преобразуется в абстрактное синтаксическое дерево (AST), и именно 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.
Встроенные типы set теперь имеют официальный C API. Вызов PySet_New() и PyFrozenSet_New() создаёт новое множество, PySet_Add() и PySet_Discard() – добавляет и удаляет элементы, а PySet_Contains() и PySet_Size() позволяют проверить состояние множества. (Предложено Raymond Hettinger.)
C-код теперь может получить информацию о точной ревизии интерпретатора Python, вызвав функцию Py_GetBuildInfo(), которая возвращает строку информации о сборке, например: "trunk:45355:45356M, Apr 13 2006, 07:42:19". (Предложено Barry Warsaw.)
Два новых макроса можно использовать для обозначения C-функций, локальных для\nтекущего файла, чтобы можно было применить более быстрое соглашение о вызове.\nPy_LOCAL(type)() объявляет функцию, возвращающую значение указанного\nтипа, и использует квалификатор быстрого вызова.\nPy_LOCAL_INLINE(type)() делает то же самое и дополнительно запрашивает\nвстраивание функции. Если PY_LOCAL_AGGRESSIVE() определено до\nвключения python.h, то для модуля включается набор более агрессивных оптимизаций;\nследует протестировать результаты, чтобы выяснить, действительно ли эти оптимизации\nускоряют код. (Предложено Фредриком Лундом на спринте NeedForSpeed.)
PyErr_NewException(name, base, dict)() теперь может принимать кортеж базовых\nклассов в качестве аргумента base. (Предложено Георгом Брандлем.)
Функция PyErr_Warn() для выдачи предупреждений теперь устарела в\nпользу PyErr_WarnEx(category, message, stacklevel)(), которая позволяет\nуказать количество стековых фреймов, разделяющих эту функцию и вызывающую. Значение\nstacklevel равное 1 – это функция, вызывающая PyErr_WarnEx(), 2 –\nфункция над ней и так далее. (Добавлено Нилом Норвицем.)
Интерпретатор CPython по-прежнему написан на C, но теперь код может быть скомпилирован компилятором C++ без ошибок. (Реализовано Энтони Бакстером, Мартином фон Лёвисом, Скипом Монтанаро.)
Функция PyRange_New() была удалена. Она никогда не документировалась, не использовалась в основном коде и имела опасно слабую проверку ошибок. В маловероятном случае, если ваши расширения её использовали, её можно заменить примерно так:
range = PyObject_CallFunction((PyObject*) &PyRange_Type, "lll", start, stop, step);
Изменения, специфичные для платформ¶Port-Specific Changes
- MacOS X (10.3 и выше): динамическая загрузка модулей теперь использует функцию dlopen() вместо MacOS-специфичных функций.
- MacOS X: в сценарий configure добавлен флаг --enable-universalsdk, который компилирует интерпретатор как универсальный бинарный файл, способный работать на процессорах PowerPC и Intel. (Автор: Ronald Oussoren; issue 2573.)
- Windows: .dll больше не поддерживается в качестве расширения файла для модулей расширений. .pyd теперь – единственное расширение, которое будет использоваться при поиске.
Перенос на Python 2.5¶Porting to Python 2.5
В этом разделе перечислены описанные ранее изменения, которые могут потребовать изменения кода:
- ASCII теперь является кодировкой по умолчанию для модулей. Теперь это синтаксическая ошибка, если модуль содержит строковые литералы с 8-битными символами, но не имеет объявления кодировки. В Python 2.4 это вызывало предупреждение, а не синтаксическую ошибку.
- Ранее атрибут gi_frame генератора всегда был объектом кадра. Из-за изменений, связанных с PEP 342, описанных в разделе PEP 342: New Generator Features, теперь gi_frame может быть None.
- Новое предупреждение UnicodeWarning срабатывает при попытке сравнить строку Unicode и 8-битную строку, которую невозможно преобразовать в Unicode с использованием кодировки ASCII по умолчанию. Ранее такие сравнения вызывали исключение UnicodeDecodeError.
- Библиотека: модуль csv теперь строже относится к многострочным полям в кавычках. Если ваши файлы содержат символы новой строки внутри полей, входные данные следует разбивать на строки так, чтобы символы новой строки сохранялись.
- Библиотека: функция format() модуля locale ранее принимала любую строку при условии, что в ней встречалось не более одного спецификатора %char. В Python 2.5 аргумент должен содержать ровно один спецификатор %char без окружающего текста.
- Библиотека: Модули pickle и cPickle больше не принимают\nвозвращаемое значение None из метода __reduce__(); метод должен\nвозвращать кортеж аргументов. Эти модули также больше не принимают устаревший\nименованный параметр bin.
- Библиотека: классы SimpleXMLRPCServer и DocXMLRPCServer теперь имеют атрибут rpc_paths, который ограничивает операции XML-RPC заданным набором путей URL; по умолчанию разрешены только '/' и '/RPC2'. Установка rpc_paths в None или пустой кортеж отключает эту проверку путей.
- C API: многие функции теперь используют Py_ssize_t вместо int, чтобы обеспечить обработку большего объёма данных на 64-разрядных машинах. Коду расширений может потребоваться внести аналогичные изменения, чтобы избежать предупреждений и поддерживать 64-разрядные машины. См. раздел PEP 353: Using ssize_t as the index type для обсуждения этого изменения.
- C API: изменения в obmalloc означают, что необходимо быть внимательным и не смешивать использование семейств функций PyMem_*() и PyObject_*(). Память, выделенная с помощью *_Malloc() одного семейства, должна освобождаться функцией *_Free() соответствующего семейства.
Благодарности¶Acknowledgements
Автор хотел бы поблагодарить следующих людей за предложения, исправления и помощь с различными черновиками этой статьи: Georg Brandl, Nick Coghlan, Phillip J. Eby, Lars Gustäbel, Raymond Hettinger, Ralf W. Grosse-Kunstleve, Kent Johnson, Iain Lowe, Martin von Löwis, Fredrik Lundh, Andrew McNamara, Skip Montanaro, Gustavo Niemeyer, Paul Prescod, James Pryor, Mike Rovner, Scott Weikart, Barry Warsaw, Thomas Wouters.