Документация Python неофициальный перевод
Содержание страницы

Что нового в Python 2.5What’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: Условные выражения. Новый оператор ‘with’ упростит написание кода очистки (раздел PEP 343: Оператор with). Теперь значения можно передавать в генераторы (раздел PEP 342: Новые возможности генераторов). Импорт теперь может быть как абсолютным, так и относительным (раздел PEP 328: Абсолютный и относительный импорт). Некоторые граничные случаи обработки исключений обрабатываются лучше (раздел PEP 341: Унифицированный try/except/finally). Все эти улучшения стоят того, но они относятся к той или иной конкретной языковой возможности; ни одно из них не является широкими изменениями семантики Python.

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

Эта статья не претендует на полную спецификацию новых возможностей; вместо этого изменения кратко представлены с помощью полезных примеров. Для получения полной информации всегда обращайтесь к документации Python 2.5 по адресу https://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’s 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’s 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). Результирующий объект является вызываемым, поэтому вы можете просто вызвать его, чтобы вызвать функцию с заполненными аргументами.

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

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() копирует атрибуты name, module и docstring в функцию-обертку, чтобы трассировки внутри обернутой функции было легче понять. Например, можно написать:

def my_decorator(f):
    def wrapper(*args, **kwds):
        print 'Calling decorated function'
        return f(*args, **kwds)
    functools.update_wrapper(wrapper, f)
    return wrapper

wraps() – это декоратор, который можно использовать внутри собственных декораторов для копирования информации обернутой функции. Альтернативная версия предыдущего примера будет:

def my_decorator(f):
    @functools.wraps(f)
    def wrapper(*args, **kwds):
        print 'Calling decorated function'
        return f(*args, **kwds)
    return wrapper

См. также

PEP 309 – Частичное применение функций

PEP предложен и написан Питером Харрисом; реализован Хё-Шиком Чангом и Ником Коглан, с адаптациями Раймонда Хеттингера.

PEP 314: Метаданные для пакетов программного обеспечения Python v1.1PEP 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 по адресу https://pypi.org – хранение архивов исходного кода и бинарных архивов для пакета. Новая команда Distutils upload будет загружать пакет в репозиторий.

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

# Импорт имён из 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 инструкции import, только с формой from ... import.

См. также

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

PEP написан Aahz; реализован Томасом Ваутерсом.

https://pylib.readthedocs.org/

Библиотека py Хольгера Крекеля, содержащая пакет 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/finallyPEP 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 был оператором; он не возвращал никакого значения. В Python 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)
        # Если передано значение, изменить 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 - Coroutines via Enhanced Generators

Авторы PEP – Guido van Rossum и Phillip J. Eby; реализация – Phillip J. Eby. Включает примеры более изощрённого использования генераторов в качестве корутин.

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

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

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

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’, никогда не узнает, что что-то пошло не так.

  • Если блок не вызвал исключения, метод __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__(), а сгенерированное значение станет возвращаемым значением метода, которое будет связано с переменной в конструкции 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, использующее новое определение типа Py_ssize_t вместо int, позволит интерпретатору обрабатывать больше данных на 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. PyArg_ParseTuple()'s s# и t# по умолчанию всё ещё выводят 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 int). NumPy определяет множество специализированных целочисленных типов, соответствующих беззнаковым и знаковым целым размером 8, 16, 32 и 64 бита, но не было способа указать, что эти типы можно использовать в качестве индексов среза.

Срезы не могут просто использовать существующий метод __int__(), потому что этот метод также используется для приведения к целым числам. Если бы срезы использовали __int__(), числа с плавающей запятой также стали бы допустимыми индексами срезов, а это явно нежелательное поведение.

Вместо этого был добавлен новый специальный метод __index__(). Он не принимает аргументов и возвращает целое число, дающее индекс среза для использования. Например:

class C:
    def __index__ (self):
        return self.value

Возвращаемое значение должно быть либо целым числом Python (int), либо длинным целым (long). Интерпретатор проверяет корректность возвращаемого типа и возбуждает TypeError, если это требование не выполнено.

Соответствующий слот nb_index был добавлен в структуру PyNumberMethods на уровне C, чтобы позволить 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) объединяет этот шаблон в один вызов метода, который возвращает кортеж из 3 элементов, содержащий подстроку до разделителя, сам разделитель и подстроку после разделителя. Если разделитель не найден, первый элемент кортежа – вся строка, а два других элемента пусты. rpartition(sep) также возвращает кортеж из 3 элементов, но начинает поиск с конца строки; 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__() класса теперь может быть как длинным целым, так и обычным целым. Если возвращается длинное целое, берется хеш этого значения. В более ранних версиях хеш-значение должно было быть обычным целым, но в 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 новое предупреждение ImportWarning возникает, когда импорт мог бы выбрать каталог в качестве пакета, но __init__.py не найден. По умолчанию это предупреждение игнорируется; для отображения сообщения укажите параметр -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. Оптимизации, добавленные на этом спринте, отмечены особым образом в следующем списке.

  • Когда встроенные типы set и frozenset были представлены в Python 2.4, они были реализованы поверх словарного типа 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.)

  • Оптимизатор "peephole" генератора кода теперь выполняет простое сворачивание констант в выражениях. Если написать что-то вроде 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 был улучшен. (Автор: Lars Immisch.)

  • Модуль codecs получил поддержку инкрементальных кодеков. Функция codec.lookup() теперь возвращает экземпляр CodecInfo вместо кортежа. Экземпляры CodecInfo ведут себя как 4-кортеж для сохранения обратной совместимости, но также имеют атрибуты encode, decode, incrementalencoder, incrementaldecoder, streamwriter и streamreader. Инкрементальные кодеки могут получать входные данные и создавать выходные по частям; результат будет таким же, как если бы все входные данные были переданы неинкрементальному кодеку. Подробнее см. документацию модуля codecs. (Разработано и реализовано Walter Dörwald.)

  • Модуль 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), который удаляет первое вхождение значения в очереди, вызывая ValueError, если значение не найдено. (Автор: Raymond Hettinger.)

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

  • Новый модуль: модуль cProfile – это реализация существующего модуля profile на языке C с гораздо меньшими накладными расходами. Интерфейс модуля такой же, как у profile: вы запускаете cProfile.run('main()') для профилирования функции, можете сохранять данные профилирования в файл и т. д. Пока неизвестно, будет ли профилировщик Hotshot, который также написан на C, но не соответствует интерфейсу модуля profile, поддерживаться в будущих версиях Python. (Автор: Armin Rigo.)

    Кроме того, модуль pstats для анализа данных, полученных профилировщиком, теперь поддерживает направление вывода в любой файловый объект путём передачи аргумента поток данных конструктору Stats. (Автор: Skip Montanaro.)

  • Модуль 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 теперь гарантирует возврат минимального списка блоков, описывающих совпадающие подпоследовательности. Ранее алгоритм иногда разбивал блок совпадающих элементов на две записи списка. (Улучшение от Tim Peters.)

  • Модуль doctest получил опцию SKIP, которая полностью предотвращает выполнение примера. Это предназначено для фрагментов кода, которые являются примерами использования для читателя и не являются тестовыми примерами.

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

  • Пакет email обновлён до версии 4.0. (Автор: Barry Warsaw.)

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

  • В модуле gc новая функция get_count() возвращает 3-кортеж, содержащий текущие счётчики коллекций для трёх поколений GC. Это учётная информация для сборщика мусора; когда эти счётчики достигают заданного порога, выполняется сборка мусора. Существующая функция gc.collect() теперь принимает необязательный аргумент generation со значениями 0, 1 или 2 для указания того, какое поколение следует собирать. (Автор: Barry Warsaw.)

  • Функции 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. Это делает её более совместимой с атрибутами объектов среза, так что теперь можно написать следующее:

    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 Installer .msi и CAB-файлы. Также включена некоторая поддержка чтения базы данных .msi. (Автор: Martin von Löwis.)

  • Модуль nis теперь поддерживает доступ к доменам, отличным от системного домена по умолчанию, путём передачи аргумента domain в функции nis.match() и nis.maps(). (Автор: Ben Bell.)

  • Функции itemgetter() и attrgetter() модуля operator теперь поддерживают несколько полей. Вызов вида operator.attrgetter('a', 'b') вернёт функцию, которая получает атрибуты a и b. Сочетание этой новой возможности с параметром key метода sort() позволяет легко сортировать списки по нескольким полям. (Автор: Raymond Hettinger.)

  • Модуль optparse обновлён до версии 1.5.1 библиотеки Optik. Класс OptionParser получил атрибут epilog – строку, которая будет выводиться после сообщения справки, и метод destroy() для разрыва циклических ссылок, создаваемых объектом. (Автор: Greg Ward.)

  • Модуль 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 также доступен, если платформа его поддерживает. (Авторы: Antti Louko и Diego Pettenò.)

  • Отладчик Python, предоставляемый модулем pdb, теперь может хранить списки команд для выполнения при достижении точки останова и остановке выполнения. После создания точки останова #1 введите commands 1 и введите серию команд для выполнения, завершив список командой end. Список команд может включать команды, возобновляющие выполнение, такие как continue или next. (Автор: Grégoire Dooms.)

  • Модули pickle и cPickle больше не принимают возвращаемое значение None от метода __reduce__(); метод теперь должен возвращать кортеж аргументов. Возможность возвращать None была объявлена устаревшей в Python 2.4, так что это завершает удаление этой возможности.

  • Модуль pkgutil, содержащий различные служебные функции для поиска пакетов, был расширен для поддержки хуков импорта PEP 302 и теперь также работает с пакетами, хранящимися в ZIP-архивах. (Автор: Phillip J. Eby.)

  • Набор тестов производительности pybench, созданный Marc-André Lemburg, теперь включён в каталог Tools/pybench. Набор pybench – это улучшение по сравнению с часто используемой программой pystone.py, поскольку pybench предоставляет более детальное измерение скорости интерпретатора. Он замеряет время отдельных операций, таких как вызовы функций, срезы кортежей, поиск методов и числовые операции, вместо того чтобы выполнять много разных операций и сводить результат к одному числу, как это делает pystone.py.

  • Модуль pyexpat теперь использует версию 2.0 парсера Expat. (Автор: Trent Mick.)

  • Класс Queue из модуля Queue получил два новых метода. join() блокируется, пока все элементы очереди не будут извлечены и вся обработка элементов не завершится. Рабочие потоки вызывают другой новый метод, task_done(), чтобы сообщить о завершении обработки элемента. (Автор: Raymond Hettinger.)

  • Старые модули regex и regsub, которые были объявлены устаревшими ещё в Python 2.0, наконец удалены. Другие удалённые модули: statcache, tzparse, whrandom.

  • Также удалён каталог lib-old, который содержал древние модули, такие как dircmp и ni. lib-old не было в sys.path по умолчанию, так что если ваши программы явно не добавляли этот каталог в sys.path, это удаление не должно повлиять на ваш код.

  • Модуль rlcompleter больше не зависит от импорта модуля readline и поэтому теперь работает на платформах, отличных от Unix. (Патч от Robert Kiendl.)

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

  • Модуль socket теперь поддерживает сокеты AF_NETLINK в Linux, благодаря патчу от Philippe Biondi. Сокеты Netlink – это специфичный для Linux механизм взаимодействия между процессом в пространстве пользователя и кодом ядра; вводная статья о них находится по адресу https://www.linuxjournal.com/article/7356. В коде Python адреса 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 были реализованы Bob Ippolito на спринте NeedForSpeed. Поддержка буферных объектов была добавлена Martin Blais, также на спринте 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". (Автор: Barry Warsaw.)

  • Ещё одна новая функция, sys._current_frames(), возвращает текущие стековые кадры для всех запущенных потоков в виде словаря, отображающего идентификаторы потоков в самый верхний стековый кадр, активный в этом потоке на момент вызова функции. (Автор: Tim Peters.)

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

    >>> import uuid
    >>> # создать UUID на основе идентификатора хоста и текущего времени
    >>> uuid.uuid1()
    UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')
    
    >>> # создать UUID с использованием MD5-хеша UUID пространства имён и имени
    >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org')
    UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e')
    
    >>> # создать случайный UUID
    >>> uuid.uuid4()
    UUID('16fd2706-8baf-433b-82eb-8c7fada847da')
    
    >>> # создать UUID с использованием SHA-1-хеша UUID пространства имён и имени
    >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org')
    UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')
    

    (Автор: 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. (Авторы: Oleg Broytmann и Georg Brandl.)

  • Модуль xmlrpclib теперь поддерживает возврат объектов datetime для типа даты XML-RPC. Передайте use_datetime=True функции loads() или классу Unmarshaller, чтобы включить эту возможность. (Автор: Skip Montanaro.)

  • Модуль zipfile теперь поддерживает формат ZIP64, то есть архив .zip может быть больше 4 ГиБ и содержать отдельные файлы размером более 4 ГиБ. (Автор: Ronald Oussoren.)

  • Объекты Compress и Decompress модуля zlib теперь поддерживают метод copy(), который создает копию внутреннего состояния объекта и возвращает новый объект Compress или Decompress. (Автор: Chris AtLee.)

Пакет ctypesThe 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. Возможно, разработчики начнут писать обертки Python поверх библиотек, доступных через ctypes, вместо модулей расширения, теперь, когда ctypes включен в ядро Python.

См. также

http://starship.python.net/crew/theller/ctypes/

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

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

Пакет ElementTreeThe 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.

Пакет hashlibThe 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')          # Указать алгоритм в виде строки

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

См. также

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

Пакет sqlite3The 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, см. https://www.sqlite.org.

См. также

http://www.pysqlite.org

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

https://www.sqlite.org

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

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

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

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

Пакет wsgirefThe wsgiref package

Web Server Gateway Interface (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 APIBuild and C API Changes

Изменения процесса сборки Python и C API включают:

  • Дерево исходного кода Python было перенесено из CVS в Subversion в ходе сложной процедуры миграции, которую курировал и безупречно выполнил Martin von Löwis. Эта процедура была разработана как PEP 347.

  • Компания Coverity, которая продаёт инструмент анализа исходного кода Prevent, предоставила результаты проверки исходного кода Python. Анализ выявил около 60 ошибок, которые были быстро исправлены. Многие из ошибок были проблемами подсчёта ссылок, часто возникавшими в коде обработки ошибок. Статистику см. на https://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 может фактически уменьшиться при их удалении, и память может быть возвращена операционной системе. (Реализовано Эваном Джонсом, доработано Тимом Питерсом.)

    Обратите внимание, что это изменение означает, что модули расширения должны быть более осторожными при выделении памяти. Python API содержит множество различных функций для выделения памяти, сгруппированных в семейства. Например, 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, локальных для текущего файла, чтобы можно было использовать более быстрый способ вызова. Py_LOCAL(type) объявляет функцию, возвращающую значение указанного типа, и использует квалификатор быстрого вызова. Py_LOCAL_INLINE(type) делает то же самое и также запрашивает встраивание функции. Если PY_LOCAL_AGGRESSIVE() определён до включения python.h, для модуля включается набор более агрессивных оптимизаций; следует выполнить бенчмаркинг результатов, чтобы выяснить, действительно ли эти оптимизации ускоряют код. (Предложено Фредриком Лундом на спринте NeedForSpeed.)

  • PyErr_NewException(name, base, dict) теперь может принимать кортеж базовых классов в качестве аргумента base. (Автор: Georg Brandl.)

  • Функция PyErr_Warn() для выдачи предупреждений теперь устарела в пользу PyErr_WarnEx(category, message, stacklevel), которая позволяет указать количество кадров стека, разделяющих эту функцию и вызывающую. stacklevel равный 1 – это функция, вызывающая PyErr_WarnEx(), 2 – функция выше, и так далее. (Добавлено Нилом Норвитцем.)

  • Интерпретатор CPython по-прежнему написан на C, но теперь код может быть скомпилирован компилятором C++ без ошибок. (Реализовано Энтони Бакстером, Мартином фон Лёвисом, Скипом Монтанаро.)

  • Функция PyRange_New() была удалена. Она никогда не была документирована, никогда не использовалась в ядре и имела опасно слабую проверку ошибок. В маловероятном случае, если ваши расширения использовали её, её можно заменить чем-то вроде следующего:

    range = PyObject_CallFunction((PyObject*) &PyRange_Type, "lll",
                                  start, stop, step);
    

Изменения, специфичные для платформPort-Specific Changes

  • MacOS X (10.3 и выше): динамическая загрузка модулей теперь использует функцию dlopen() вместо функций, специфичных для MacOS.

  • MacOS X: в скрипт configure добавлен флаг --enable-universalsdk, который компилирует интерпретатор как универсальный бинарный файл, способный работать как на процессорах PowerPC, так и Intel. (Автор: Ronald Oussoren; bpo-2573.)

  • Windows: .dll больше не поддерживается как расширение имени файла для модулей расширения. .pyd теперь единственное расширение имени файла, которое будет искаться.

Перенос на Python 2.5Porting to Python 2.5

В этом разделе перечислены описанные ранее изменения, которые могут потребовать изменения кода:

  • ASCII теперь является кодировкой по умолчанию для модулей. Теперь это синтаксическая ошибка, если модуль содержит строковые литералы с 8-битными символами, но не имеет объявления кодировки. В Python 2.4 это вызывало предупреждение, а не синтаксическую ошибку.

  • Ранее атрибут gi_frame генератора всегда был объектом frame. Благодаря изменениям PEP 342, описанным в разделе PEP 342: Новые возможности генераторов, теперь gi_frame может быть None.

  • Новое предупреждение UnicodeWarning возникает при попытке сравнить строку Unicode и 8-битную строку, которую невозможно преобразовать в Unicode с использованием кодировки ASCII по умолчанию. Ранее такие сравнения вызывали исключение UnicodeDecodeError.

  • Библиотека: модуль csv теперь более строг к многострочным полям в кавычках. Если файлы содержат символы новой строки внутри полей, входные данные следует разбивать на строки таким образом, чтобы сохранить символы новой строки.

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

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

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

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

  • C API: изменения obmalloc означают, что нужно быть внимательным и не смешивать использование семейств функций PyMem_*() и PyObject_*(). Память, выделенная с помощью *_Malloc() одного семейства, должна освобождаться с помощью *_Free() соответствующего семейства.

Благодарности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.