Что нового в Python 2.5

Автор:

А.М. Кючлинг

В этой статье рассказывается о новых возможностях Python 2.5. Финальный выпуск Python 2.5 запланирован на август 2006 года; PEP 356 описывает планируемый график выпуска. Python 2.5 был выпущен 19 сентября 2006 года.

Изменения в Python 2.5 представляют собой интересную смесь улучшений языка и библиотеки. Улучшения в библиотеке, как мне кажется, будут более важны для сообщества пользователей Python, потому что было добавлено несколько широко полезных пакетов. Среди новых модулей - ElementTree для обработки XML (xml.etree), модуль базы данных SQLite (sqlite) и модуль ctypes для вызова функций C.

Изменения в языке имеют среднее значение. Было добавлено несколько приятных новых функций, но большинство из них не являются функциями, которые вы будете использовать каждый день. В язык наконец-то были добавлены условные выражения с использованием нового синтаксиса; см. раздел PEP 308: Условные выражения. Новый оператор „with упростит написание очищающего кода (раздел PEP 343: Утверждение „с“). Значения теперь можно передавать в генераторы (раздел PEP 342: Новые возможности генератора). Импорты теперь видны как абсолютные или относительные (раздел PEP 328: Абсолютный и относительный импорт). Некоторые угловые случаи обработки исключений стали обрабатываться лучше (раздел PEP 341: Унифицированные try/except/finally). Все эти улучшения достойны внимания, но они представляют собой усовершенствования тех или иных особенностей языка; ни одно из них не является широкой модификацией семантики Python.

Помимо дополнений к языку и библиотекам, в дерево исходных текстов были внесены другие улучшения и исправления ошибок. Поиск по журналам изменений SVN показывает, что между Python 2.4 и 2.5 было применено 353 исправления и исправлено 458 ошибок. (Обе цифры, скорее всего, занижены).

Эта статья не претендует на полное описание новых возможностей; вместо этого изменения кратко представлены на полезных примерах. За подробной информацией всегда следует обращаться к документации по Python 2.5 на сайте https://docs.python.org. Если вы хотите понять полную реализацию и обоснование дизайна, обратитесь к PEP для конкретной новой функции.

Комментарии, предложения и сообщения об ошибках в этом документе приветствуются; пожалуйста, отправьте их автору по электронной почте или откройте ошибку в трекере ошибок Python.

PEP 308: Условные выражения

Уже давно люди просят дать им возможность писать условные выражения - выражения, которые возвращают значение A или B в зависимости от того, истинно или ложно булево значение. Условное выражение позволяет написать один оператор присваивания, который имеет тот же эффект, что и следующий:

if condition:
    x = true_value
else:
    x = false_value

Как на python-dev, так и на comp.lang.python велись бесконечные утомительные обсуждения синтаксиса. Было даже проведено голосование, которое показало, что большинство проголосовавших хотят условные выражения в той или иной форме, но не было синтаксиса, которому отдало бы предпочтение явное большинство. Среди кандидатов были cond ? true_v : false_v, if cond then true_v else false_v и 16 других вариантов.

В итоге Гвидо ван Россум выбрал неожиданный синтаксис:

x = true_value if condition else false_value

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

Такой синтаксис может показаться странным и обратным: почему условие находится в середине выражения, а не впереди, как в c ? x : y в языке C? Это решение было проверено путем применения нового синтаксиса к модулям стандартной библиотеки и просмотра того, как читается полученный код. Во многих случаях, когда используется условное выражение, одно значение кажется «обычным случаем», а другое - «исключительным случаем», используемым только в редких случаях, когда условие не выполняется. Синтаксис условных выражений делает эту схему более очевидной:

contents = ((doc + '\n') if doc else '')

Я прочитал приведенное выше утверждение как означающее «здесь contents обычно присваивается значение doc+'\n'; иногда doc бывает пустым, и в этом случае возвращается пустая строка». Я сомневаюсь, что буду часто использовать условные выражения, где нет четкого общего и особого случая.

Обсуждался вопрос о том, должен ли язык требовать окружения условных выражений круглыми скобками. Было принято решение не требовать скобок в грамматике языка Python, но в качестве стилистики я считаю, что вы должны всегда их использовать. Рассмотрим эти два утверждения:

# First version -- no parens
level = 1 if logging else 0

# Second version -- with parens
level = (1 if logging else 0)

В первом варианте, как мне кажется, читатель может сгруппировать утверждение на „level = 1“, „if logging“, „else 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). Полученный объект является вызываемым, поэтому вы можете просто вызвать его, чтобы вызвать функцию с заполненными аргументами.

Вот небольшой, но реалистичный пример:

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

В 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: Абсолютный и относительный импорт

В Python 2.4 была реализована более простая часть PEP 328: теперь можно было заключать в круглые скобки имена, импортируемые из модуля с помощью оператора 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 Хольгера Крекеля обеспечивает более аккуратный способ импорта из стандартной библиотеки, 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:

# Import names from pkg.string
from .string import name1, name2
# Import pkg.string
from . import string

Это импортирует модуль string относительно текущего пакета, так что в pkg.main это импортирует name1 и name2 из pkg.string. Дополнительные лидирующие периоды выполняют относительный импорт, начиная с родителя текущего пакета. Например, код в модуле A.B.C может делать:

from . import D                 # Imports A.B.D
from .. import E                # Imports A.E
from ..F import G               # Imports A.F.G

Ведущие периоды не могут использоваться в форме import modname оператора импорта, только в форме from ... import.

См.также

PEP 328 - Импорт: Многострочный и абсолютный/относительный

PEP написан Aahz; реализован Thomas Wouters.

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

Выполняется код в блоке-1. Если код вызывает исключение, проверяются различные блоки except: если исключение относится к классу Exception1, выполняется handler-1, если к классу Exception2, выполняется handler-2, и так далее. Если исключение не возникло, выполняется else-блок.

Независимо от того, что произошло ранее, final-block выполняется, как только блок кода завершен и все поднятые исключения обработаны. Даже если в обработчике исключений или в else-блоке произошла ошибка и было поднято новое исключение, код в финальном блоке все равно будет выполнен.

См.также

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 возвращает указанное значение. Если вызывается регулярный метод next(), то выражение yield возвращает значение None.

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

def counter (maximum):
    i = 0
    while i < maximum:
        val = (yield i)
        # If value provided, change 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 генератора всегда был объектом кадра. Теперь, когда генератор исчерпан, gi_frame может стать None.

См.также

PEP 342 - Корутины через расширенные генераторы

PEP, написанный Гвидо ван Россумом и Филлипом Дж. Эби; реализованный Филлипом Дж. Эби. Включает примеры более сложного использования генераторов в качестве коротинов.

Более ранние версии этих функций были предложены в PEP 288 Раймонда Хеттингера и PEP 325 Самуэле Педрони.

https://en.wikipedia.org/wiki/Coroutine

Запись в Википедии о корутинах.

https://web.archive.org/web/20160321211320/http://www.sidhe.org/~dan/blog/archives/000178.html

Объяснение корутинов с точки зрения Perl, написанное Дэном Шугальски.

PEP 343: Утверждение „с“

Утверждение „with“ уточняет код, который ранее использовал блоки try...finally для обеспечения выполнения кода очистки. В этом разделе я расскажу об утверждении в том виде, в котором оно обычно используется. В следующем разделе я рассмотрю детали реализации и покажу, как писать объекты для использования этого оператора.

Оператор „with“ представляет собой новую структуру потока управления, базовой структурой которой является:

with expression [as variable]:
    with-block

Выражение оценивается, и в результате должен получиться объект, поддерживающий протокол управления контекстом (то есть имеющий методы __enter__() и __exit__()).

Функция __enter__() объекта вызывается до выполнения with-block и поэтому может выполнять код установки. Он также может вернуть значение, связанное с именем переменной, если оно задано. (Обратите внимание, что переменная не присваивается результату выражения).

После завершения выполнения 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(), потому что __enter__() возвращает self.

Блокировки и переменные условия модуля threading также поддерживают оператор „with:

lock = threading.Lock()
with lock:
    # Critical section of code
    ...

Блокировка приобретается перед выполнением блока и всегда освобождается после его завершения.

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

from decimal import Decimal, Context, localcontext

# Displays with default precision of 28 digits
v = Decimal('578')
print v.sqrt()

with localcontext(Context(prec=16)):
    # All code in this block uses a precision of 16 digits.
    # The original context is restored on exiting the block.
    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 ...')
    # ... more operations ...

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

class DatabaseConnection:
    # Database interface
    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):
        # Code to start a new transaction
        cursor = self.cursor()
        return cursor

Метод __exit__() является самым сложным, потому что именно в нем выполняется большая часть работы. Метод должен проверить, не произошло ли исключение. Если исключения не было, транзакция фиксируется. Если исключение имело место, транзакция откатывается.

В приведенном ниже коде выполнение просто отвалится в конец функции, вернув значение по умолчанию None. None равно false, поэтому исключение будет вызвано автоматически. При желании вы можете быть более явными и добавить оператор return в отмеченное место.

class DatabaseConnection:
    ...
    def __exit__ (self, type, value, tb):
        if tb is None:
            # No exception, so commit
            self.commit()
        else:
            # Exception occurred, so rollback.
            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.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 - Утверждение «с»

PEP, написанный Гвидо ван Россумом и Ником Когланом; реализованный Майком Бландом, Гвидо ван Россумом и Нилом Норвицем. PEP показывает код, генерируемый для оператора „with“, что может быть полезно для изучения работы этого оператора.

Документация для модуля contextlib.

PEP 352: Исключения как классы нового стиля

Классы исключений теперь могут быть классами нового стиля, а не только классическими классами. Встроенный класс Exception и все стандартные встроенные исключения (NameError, ValueError и т. д.) теперь являются классами нового стиля.

Иерархия наследования для исключений была немного перестроена. В 2.5 отношения наследования выглядят следующим образом:

BaseException       # New in 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:
    # Log error...
    # Continue running program...

В 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 в качестве типа индекса

Широкомасштабное изменение в API Python на языке C, использующее новое определение типа Py_ssize_t вместо int, позволит интерпретатору обрабатывать больше данных на 64-битных платформах. Это изменение не влияет на возможности Python на 32-битных платформах.

Различные части интерпретатора Python использовали тип int языка Си для хранения размеров или подсчетов; например, количество элементов в списке или кортеже хранилось в int. Компиляторы языка Си для большинства 64-битных платформ по-прежнему определяют int как 32-битный тип, поэтому списки могли содержать только до 2**31 - 1 = 2147483647 элементов. (На самом деле существует несколько различных моделей программирования, которые могут использовать 64-битные компиляторы C - см. https://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. Функции PyArg_ParseTuple() s# и t# по умолчанию по-прежнему выводят int, но вы можете определить макрос PY_SSIZE_T_CLEAN перед включением Python.h, чтобы они возвращали Py_ssize_t.

PEP 353 содержит раздел о рекомендациях по преобразованию, который следует прочитать авторам расширений, чтобы узнать о поддержке 64-битных платформ.

См.также

PEP 353 - Использование ssize_t в качестве типа индекса

PEP написан и реализован Мартином фон Лёвисом.

PEP 357: Метод „__index__“

Разработчики NumPy столкнулись с проблемой, которую можно было решить только добавлением нового специального метода __index__(). При использовании нотации slice, как в [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-битных строках, так и в строках Unicode появились новые методы partition(sep) и rpartition(sep), которые упрощают часто используемые случаи.

    Метод find(S) часто используется для получения индекса, который затем используется для разрезания строки и получения фрагментов, которые находятся до и после разделителя. Метод partition(sep) сводит эту схему к одному вызову метода, который возвращает кортеж из трех элементов, содержащий подстроку перед разделителем, сам разделитель и подстроку после разделителя. Если разделитель не найден, то первым элементом кортежа будет вся строка, а два других элемента будут пустыми. 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']
    # Prints 'longest'
    print max(L, key=len)
    # Prints 'short', because lexicographically 'short' has the largest value
    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 по умолчанию. Результатом сравнения является false:

    >>> chr(128) == unichr(128)   # Can't convert chr(128) to 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) can be converted
    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. По умолчанию это предупреждение молча игнорируется; чтобы вывести предупреждение, при запуске исполняемого файла Python укажите опцию -Wd. (Реализовано Томасом Воутерсом).

  • Список базовых классов в определении класса теперь может быть пустым. В качестве примера можно привести следующее:

    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 внутренняя структура данных была адаптирована для реализации наборов, в результате чего наборы будут использовать на треть меньше памяти и работать несколько быстрее. (Реализовано Раймондом Хеттингером).

  • Повышена скорость выполнения некоторых операций с Unicode, таких как поиск подстрок, разбиение строк, кодирование и декодирование карт символов. (Улучшения поиска и разбиения подстрок были добавлены Фредриком Лундом и Эндрю Далком в ходе спринта 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), который удаляет первое вхождение значения в очереди, вызывая ValueError, если значение не найдено. (Внесено Раймондом Хеттингером).

  • Новый модуль: Модуль contextlib содержит вспомогательные функции для использования с новым оператором „with. Подробнее об этом модуле см. в разделе Модуль contextlib.

  • Новый модуль: Модуль cProfile - это реализация на языке C существующего модуля profile, имеющая гораздо меньшие накладные расходы. Интерфейс модуля такой же, как и у profile: вы запускаете cProfile.run('main()') для профилирования функции, можете сохранять данные профиля в файл и т. д. Пока неизвестно, будет ли профилировщик Hotshot, который также написан на C, но не соответствует интерфейсу модуля profile, поддерживаться в будущих версиях 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, которая не дает примеру выполняться вообще. Это предназначено для фрагментов кода, которые являются примерами использования, предназначенными для читателя, и не являются собственно тестовыми примерами.

    В функцию testfile() и класс DocFileSuite был добавлен параметр encoding для указания кодировки файла. Это упрощает использование символов не ASCII в тестах, содержащихся в строке документации. (Внесено Бьорном Тиллениусом).

  • Пакет email был обновлен до версии 4.0. (Предоставлено Барри Варшавой.)

  • Модуль fileinput стал более гибким. Теперь поддерживаются юникодные имена файлов, а в функцию input() добавлен параметр mode, по умолчанию равный "r", позволяющий открывать файлы в двоичном или universal newlines режиме. Еще один новый параметр, openhook, позволяет использовать функцию, отличную от open(), для открытия входных файлов. После итерации по набору файлов новый параметр FileInput объекта fileno() возвращает дескриптор текущего открытого файла. (Внесено Георгом Брандлом.)

  • В модуле gc новая функция get_count() возвращает 3-кортеж, содержащий текущие значения количества сборок для трех поколений 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)  # Return two lowest elements, lexicographically
    ['longer still', 'longest']
    >>> heapq.nsmallest(2, L, key=len)   # Return two shortest elements
    ['short', 'medium']
    

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

  • Функция itertools.islice() теперь принимает None в качестве аргументов начала и шага. Это делает ее более совместимой с атрибутами объектов slice, так что теперь вы можете написать следующее:

    s = slice(5)     # Create slice object
    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' uses email.Message.Message as the class representing
    # individual messages.
    src = mailbox.Maildir('maildir', factory=None)
    dest = mailbox.mbox('/tmp/mbox')
    
    for msg in src:
        dest.add(msg)
    

    (Внесено Грегори К. Джонсоном. Финансирование было предоставлено Google в рамках программы 2005 Summer of Code).

  • Новый модуль: модуль msilib позволяет создавать файлы Microsoft Installer .msi и CAB-файлы. Также включена некоторая поддержка чтения базы данных .msi. (Внесено Мартином фон Лёвисом).

  • Модуль nis теперь поддерживает доступ к доменам, отличным от системного домена по умолчанию, путем указания аргумента domain в функциях nis.match() и nis.maps(). (Внесено Беном Беллом.)

  • Функции operator модуля itemgetter() и attrgetter() теперь поддерживают несколько полей. Вызов, например 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) принимает идентификатор процесса. (Внесено Чадом Дж. Шредером).

    Во 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 механизм связи между процессом в пользовательском пространстве и кодом ядра; вводная статья о них находится на 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).

  • В процессе разработки 2.5 разработчики Python перешли с CVS на Subversion. Информация о точной версии сборки доступна в виде переменной 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 threading и OS/2 поддерживают. (Внесено Эндрю Макинтайром.)

  • Модуль 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. (UUID версии 2 не указаны в RFC 4122 и не поддерживаются этим модулем).

    >>> import uuid
    >>> # make a UUID based on the host ID and current time
    >>> uuid.uuid1()
    UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')
    
    >>> # make a UUID using an MD5 hash of a namespace UUID and a name
    >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org')
    UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e')
    
    >>> # make a random UUID
    >>> uuid.uuid4()
    UUID('16fd2706-8baf-433b-82eb-8c7fada847da')
    
    >>> # make a UUID using a SHA-1 hash of a namespace UUID and a name
    >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org')
    UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')
    

    (Предоставлено Ка-Пинг Йи.)

  • Типы weakref модуля WeakKeyDictionary и WeakValueDictionary получили новые методы для итерации по слабым ссылкам, содержащимся в словаре. Методы 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 Гб. (Внесено Рональдом Уссореном).

  • Объекты zlib модуля Compress и Decompress теперь поддерживают метод 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, но для других типов вы должны вызвать правильный конструктор типов. (И я имею в виду должны; неправильный вызов часто приводит к аварийному завершению работы интерпретатора с ошибкой сегментации).

Не следует использовать 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 is now {'abc', 1}.

Не забудьте использовать py_object(); если его пропустить, вы получите ошибку сегментации.

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

См.также

https://web.archive.org/web/20180410025338/http://starship.python.net/crew/theller/ctypes/

Веб-страница ctypes, созданная до появления stdlib, с учебником, справочником и FAQ.

Документация для модуля ctypes.

Пакет ElementTree

Подмножество библиотеки ElementTree Фредрика Лунда для обработки XML было добавлено в стандартную библиотеку как xml.etree. Доступны модули ElementTree, ElementPath и ElementInclude из ElementTree 1.2.6. Также включен модуль ускорителя cElementTree.

В остальной части этого раздела будет дан краткий обзор использования ElementTree. Полная документация по ElementTree доступна на сайте https://web.archive.org/web/20201124024954/http://effbot.org/zone/element-index.htm.

ElementTree представляет XML-документ в виде дерева узлов-элементов. Текстовое содержимое документа хранится в виде атрибутов text и tail (Это одно из основных отличий ElementTree от Document Object Model; в 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’th дочерний элемент.

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(), он может принимать либо строку, либо файлоподобный объект:

# Encoding is US-ASCII
tree.write('output.xml')

# Encoding is UTF-8
f = open('output.xml', 'w')
tree.write(f, encoding='utf-8')

(Внимание: по умолчанию для вывода используется кодировка ASCII. Для общей работы с XML, где имя элемента может содержать произвольные символы Unicode, ASCII не очень удобная кодировка, поскольку она вызовет исключение, если имя элемента содержит символы со значением больше 127. Поэтому лучше указать другую кодировку, например UTF-8, которая может обрабатывать любые символы Юникода).

Этот раздел - лишь частичное описание интерфейсов ElementTree. Для получения более подробной информации читайте официальную документацию пакета.

См.также

https://web.archive.org/web/20201124024954/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, чтобы сохранить обратную совместимость. Интерфейс нового модуля очень близок к интерфейсу старых модулей, но не идентичен. Наиболее существенным отличием является то, что функции-конструкторы для создания новых объектов хэширования называются по-другому.

# Old versions
h = md5.md5()
h = md5.new()

# New version
h = hashlib.md5()

# Old versions
h = sha.sha()
h = sha.new()

# New version
h = hashlib.sha1()

# Hash that weren't previously available
h = hashlib.sha224()
h = hashlib.sha256()
h = hashlib.sha384()
h = hashlib.sha512()

# Alternative form
h = hashlib.new('md5')          # Provide algorithm as a string

После создания хэш-объекта его методы остаются прежними: update(string) хэширует указанную строку в текущее состояние digest, digest() и hexdigest() возвращают значение digest в виде двоичной строки или строки шестнадцатеричных цифр, а copy() возвращает новый хэш-объект с тем же состоянием digest.

См.также

Документация для модуля hashlib.

Пакет sqlite3

Модуль pysqlite (https://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()

# Create table
c.execute('''create table stocks
(date text, trans text, symbol text,
 qty real, price real)''')

# Insert a row of data
c.execute("""insert into stocks
          values ('2006-01-05','BUY','RHAT',100,35.14)""")

Обычно в операциях SQL необходимо использовать значения из переменных Python. Вы не должны собирать запрос, используя строковые операции Python, потому что это небезопасно; это делает вашу программу уязвимой для атаки SQL-инъекции.

Вместо этого используйте подстановку параметров DB-API. Поместите ? в качестве заполнителя везде, где вы хотите использовать значение, а затем предоставьте кортеж значений в качестве второго аргумента метода execute() курсора. (В других модулях баз данных может использоваться другое значение, например %s или :1). Например:

# Never do this -- insecure!
symbol = 'IBM'
c.execute("... where symbol = '%s'" % symbol)

# Do this instead
t = (symbol,)
c.execute('select * from stocks where symbol=?', t)

# Larger example
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.

См.также

https://www.pysqlite.org

Веб-страница pysqlite.

https://www.sqlite.org

Веб-страница SQLite; документация описывает синтаксис и доступные типы данных для поддерживаемого диалекта SQL.

Документация для модуля sqlite3.

PEP 249 - Спецификация API баз данных 2.0

PEP написан Марком-Андре Лембургом.

Пакет wsgiref

Интерфейс шлюза веб-сервера (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()

См.также

https://web.archive.org/web/20160331090247/http://wsgi.readthedocs.org/en/latest/

Центральный веб-сайт для ресурсов, связанных с 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.

  • Самое большое изменение в API языка C было сделано в разделе 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 выделял небольшие объекты в аренах размером 256K, но никогда не освобождал арены. С этим патчем 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.

  • Встроенные типы множеств теперь имеют официальный API на языке C. Вызовите 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". (Внесено Барри Варшавой.)

  • Два новых макроса могут использоваться для обозначения функций языка Си, локальных для текущего файла, чтобы можно было использовать более быстрый вызов. Py_LOCAL(type) объявляет функцию как возвращающую значение указанного типа и использует квалификатор быстрого вызова. Макрос Py_LOCAL_INLINE(type) делает то же самое, а также запрашивает вставку функции. Если макрос PY_LOCAL_AGGRESSIVE определен до включения python.h, для модуля включается набор более агрессивных оптимизаций; чтобы узнать, действительно ли эти оптимизации делают код быстрее, следует провести сравнительный анализ результатов. (Внесено Фредриком Лундом на спринте NeedForSpeed).

  • PyErr_NewException(name, base, dict) теперь может принимать кортеж базовых классов в качестве аргумента base. (Внесено Георгом Брандлом).

  • Функция PyErr_Warn() для выдачи предупреждений теперь устарела в пользу PyErr_WarnEx(category, message, 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 теперь строже относится к многострочным полям с кавычками. Если ваши файлы содержат символы новой строки, встроенные в поля, ввод должен быть разделен на строки таким образом, чтобы сохранить символы новой строки.

  • Библиотека: функции locale модуля format() ранее принимали любую строку, если в ней было не более одного спецификатора %char. В Python 2.5 аргумент должен состоять ровно из одного спецификатора %char без окружающего текста.

  • Библиотека: Модули pickle и cPickle больше не принимают возвращаемое значение None от метода __reduce__(); вместо этого метод должен возвращать кортеж аргументов. Модули также больше не принимают устаревший параметр ключевого слова bin.

  • Библиотека: Классы SimpleXMLRPCServer и DocXMLRPCServer теперь имеют атрибут rpc_paths, который ограничивает операции XML-RPC ограниченным набором URL-путей; по умолчанию разрешены только '/' и '/RPC2'. Установка rpc_paths в None или пустой кортеж отключает эту проверку путей.

  • API НА ЯЗЫКЕ C: Многие функции теперь используют Py_ssize_t вместо int, что позволяет обрабатывать больше данных на 64-битных машинах. Коду расширений может потребоваться внести такое же изменение, чтобы избежать предупреждений и поддерживать 64-битные машины. Обсуждение этого изменения см. в предыдущем разделе PEP 353: Использование ssize_t в качестве типа индекса.

  • API НА ЯЗЫКЕ C: Изменения в obmalloc означают, что вы должны быть осторожны, чтобы не смешивать использование семейств функций PyMem_* и PyObject_*. Память, выделенная с помощью функции *_Malloc одного семейства, должна быть освобождена с помощью функции *_Free соответствующего семейства.

Благодарности

Автор хотел бы поблагодарить следующих людей за предложения, исправления и помощь в работе над различными черновиками этой статьи: 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.