Содержание страницы
Что нового в Python 2.5¶What’s New in Python 2.5
- Автор:
A.M. Kuchling
В этой статье описываются новые возможности Python 2.5. Финальный релиз Python 2.5 был запланирован на август 2006 года; PEP 356 описывает запланированный график выпуска. Python 2.5 был выпущен 19 сентября 2006 года.
Изменения в 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.1¶PEP 314: Metadata for Python Software Packages v1.1
В Distutils добавлена простая поддержка зависимостей. Функция setup() теперь имеет именованные параметры requires, provides и obsoletes. При сборке дистрибутива исходного кода с помощью команды sdist информация о зависимостях будет записана в файл PKG-INFO.
Ещё один новый именованный параметр – download_url. Он должен указывать на URL исходного кода пакета. Это означает, что теперь можно найти запись в индексе пакетов, определить зависимости пакета и загрузить необходимые пакеты.
VERSION = '1.0'
setup(name='PyPackage',
version=VERSION,
requires=['numarray', 'zlib (>=1.1.4)'],
obsoletes=['OldPackage']
download_url=('http://www.example.com/pypackage/dist/pkg-%s.tar.gz'
% VERSION),
)
Ещё одно новое усовершенствование индекса пакетов Python по адресу 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.io/
Библиотека 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/finally¶PEP 341: Unified try/except/finally
До Python 2.5 инструкция try существовала в двух вариантах. Можно было использовать блок finally, чтобы гарантировать выполнение кода в любом случае, или один или несколько блоков except для перехвата определённых исключений. Нельзя было комбинировать блоки except и блок finally, потому что генерация правильного байт-кода для комбинированного варианта была сложной, и было неясно, какой должна быть семантика такой инструкции.
Гвидо ван Россум некоторое время работал с Java, в которой поддерживается комбинация блоков except и блока finally, и это прояснило, каким должно быть значение инструкции. В Python 2.5 теперь можно писать:
try:
block-1 ...
except Exception1:
handler-1 ...
except Exception2:
handler-2 ...
else:
else-block
finally:
final-block
Сначала выполняется код в block-1. Если код возбуждает исключение, проверяются различные блоки except: если исключение относится к классу Exception1, выполняется handler-1; иначе если к классу Exception2, выполняется handler-2 и так далее. Если исключение не возбуждено, выполняется else-block.
Независимо от того, что произошло ранее, блок finally выполняется после завершения блока кода и обработки всех возникших исключений. Даже если в обработчике исключения или в блоке else произошла ошибка и возникло новое исключение, код в блоке finally всё равно выполняется.
См. также
- PEP 341 – Объединение try-except и try-finally
Автор PEP – Georg Brandl; реализация – Thomas Lee.
PEP 342: Новые возможности генераторов¶PEP 342: New Generator Features
Python 2.5 добавляет простой способ передачи значений в генератор. Как было введено в Python 2.3, генераторы только выдают результат; после того как код генератора был вызван для создания итератора, не было возможности передать какую-либо новую информацию в функцию при возобновлении её выполнения. Иногда возможность передать какую-то информацию была бы полезна. Кустарные решения этой проблемы включали просмотр кодом генератора глобальной переменной и последующее изменение её значения, либо передачу изменяемого объекта, который вызывающие стороны затем модифицируют.
Чтобы освежить в памяти основы генераторов, вот простой пример:
def counter (maximum):
i = 0
while i < maximum:
yield i
i += 1
При вызове counter(10) результатом является итератор, который возвращает значения от 0 до 9. При встрече с оператором yield итератор возвращает указанное значение и приостанавливает выполнение функции, сохраняя локальные переменные. Выполнение возобновляется при следующем вызове метода next() итератора, продолжая после оператора yield.
В Python 2.3 yield был оператором; он не возвращал никакого значения. В 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
Статья в Википедии о корутинах.
- https://web.archive.org/web/20160321211320/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(), поскольку
__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.
Если в BLOCK возникает исключение, вызывается метод
__exit__(type, value, traceback)с деталями исключения – теми же значениями, которые возвращаетsys.exc_info(). Возвращаемое значение метода определяет, будет ли исключение возбуждено повторно: любое ложное значение приводит к повторному возбуждению, аTrueприведёт к его подавлению. Подавлять исключение стоит крайне редко, потому что в этом случае автор кода, содержащего оператор ‘with’, никогда не узнает, что что-то пошло не так.Если BLOCK не вызвал исключения, метод
__exit__()всё равно вызывается, но type, value и traceback равныNone.
Рассмотрим пример. Я не буду приводить подробный код, а только набросаю методы, необходимые для базы данных, поддерживающей транзакции.
(Для тех, кто не знаком с терминологией баз данных: набор изменений базы данных группируется в транзакцию. Транзакция может быть либо зафиксирована (committed) – это означает, что все изменения записываются в базу данных, – либо откачена (rolled back) – это означает, что все изменения отбрасываются, и база данных остаётся без изменений. За дополнительной информацией обратитесь к любому учебнику по базам данных.)
Предположим, есть объект, представляющий подключение к базе данных. Наша цель – позволить пользователю писать код вроде такого:
db_connection = DatabaseConnection()
with db_connection as cursor:
cursor.execute('insert into ...')
cursor.execute('delete from ...')
# ... ещё операции ...
Транзакция должна быть зафиксирована, если код в блоке выполняется без ошибок, или откачена, если возникло исключение. Вот базовый интерфейс для DatabaseConnection, который я предполагаю:
class DatabaseConnection:
# Интерфейс базы данных
def cursor (self):
"Returns a cursor object and starts a new transaction"
def commit (self):
"Commits current transaction"
def rollback (self):
"Rolls back current transaction"
Метод __enter__() довольно прост – ему нужно лишь начать новую транзакцию. Для этого приложения результирующий объект курсора будет полезным результатом, поэтому метод возвращает его. Затем пользователь может добавить as cursor в свой оператор ‘with’, чтобы связать курсор с именем переменной.
class DatabaseConnection:
...
def __enter__ (self):
# Код для начала новой транзакции
cursor = self.cursor()
return cursor
Метод __exit__() самый сложный, поскольку именно в нём должна выполняться большая часть работы. Метод должен проверить, возникло ли исключение. Если исключения не было, транзакция фиксируется. Если было – транзакция откатывается.
В приведённом ниже коде выполнение просто дойдёт до конца функции, вернув значение по умолчанию None. None – ложное значение, поэтому исключение будет возбуждено повторно автоматически. При желании можно быть более явным и добавить оператор return в отмеченном месте.
class DatabaseConnection:
...
def __exit__ (self, type, value, tb):
if tb is None:
# Нет исключения, поэтому коммит
self.commit()
else:
# Произошло исключение, поэтому откат.
self.rollback()
# return False
Модуль contextlib¶The contextlib module
Новый модуль contextlib предоставляет несколько функций и декоратор, которые полезны для написания объектов, используемых с оператором ‘with’.
Декоратор называется contextmanager() и позволяет написать одну функцию-генератор вместо определения нового класса. Генератор должен генерировать ровно одно значение. Код до yield будет выполнен как метод __enter__(), а сгенерированное значение станет возвращаемым значением метода, которое будет связано с переменной в конструкции 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 – см. обсуждение на 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 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 (значения, разделённые запятыми), получил несколько улучшений и ряд исправлений ошибок. Теперь можно задать максимальный размер поля в байтах, вызвав функцию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():import datetime as dt ts = dt.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, так что это завершает удаление этой возможности.The
pkgutilmodule, containing various utility functions for finding packages, was enhanced to support PEP 302’s import hooks and now also works for packages stored in ZIP-format archives. (Contributed by 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.)
Пакет ctypes¶The ctypes package
Пакет ctypes, написанный Томасом Хеллером, был добавлен в стандартную библиотеку. ctypes позволяет вызывать произвольные функции в разделяемых библиотеках или DLL. Постоянные пользователи могут помнить модуль dl, который предоставляет функции для загрузки разделяемых библиотек и вызова в них функций. Пакет ctypes гораздо навороченнее.
Чтобы загрузить разделяемую библиотеку или DLL, необходимо создать экземпляр класса CDLL и указать имя или путь к разделяемой библиотеке или DLL. После этого можно вызывать произвольные функции, обращаясь к ним как к атрибутам объекта CDLL.
import ctypes
libc = ctypes.CDLL('libc.so.6')
result = libc.printf("Line of output\n")
Предоставляются конструкторы типов для различных типов C: c_int(), c_float(), c_double(), c_char_p() (эквивалентно char*) и так далее. В отличие от типов Python, версии C все изменяемы; можно присвоить их атрибуту value, чтобы изменить обернутое значение. Целые числа и строки Python будут автоматически преобразованы в соответствующие типы C, но для других типов необходимо вызывать правильный конструктор типа. (И я имею в виду необходимо; если ошибиться, это часто приводит к падению интерпретатора с ошибкой сегментации.)
Не следует использовать c_char_p() с строкой Python, если функция C будет изменять область памяти, поскольку строки Python считаются неизменяемыми; нарушение этого правила приведет к труднообъяснимым ошибкам. Когда требуется изменяемая область памяти, используйте create_string_buffer():
s = "this is a string"
buf = ctypes.create_string_buffer(s)
libc.strfry(buf)
Предполагается, что функции C возвращают целые числа, но можно установить атрибут restype объекта функции, чтобы изменить это:
>>> libc.atof('2.71828')
-1783957616
>>> libc.atof.restype = ctypes.c_double
>>> libc.atof('2.71828')
2.71828
ctypes также предоставляет обертку для C API Python в виде объекта ctypes.pythonapi. Этот объект не освобождает глобальную блокировку интерпретатора перед вызовом функции, поскольку блокировка должна быть удержана при вызове кода интерпретатора. Существует конструктор типа py_object, который создает указатель PyObject*. Простой пример использования:
import ctypes
d = {}
ctypes.pythonapi.PyObject_SetItem(ctypes.py_object(d),
ctypes.py_object("abc"), ctypes.py_object(1))
# d теперь содержит {'abc', 1}.
Не забывайте использовать py_object(); если его пропустить, получите ошибку сегментации.
ctypes существует уже некоторое время, но люди всё ещё пишут и распространяют собственноручно написанные модули расширения, потому что нельзя полагаться на наличие ctypes. Возможно, разработчики начнут писать обертки Python поверх библиотек, доступных через ctypes, вместо модулей расширения, теперь, когда ctypes включен в ядро Python.
См. также
- https://web.archive.org/web/20180410025338/http://starship.python.net/crew/theller/ctypes/
Веб-страница ctypes до включения в стандартную библиотеку, с учебным пособием, справочником и FAQ.
Документация модуля ctypes.
Пакет ElementTree¶The ElementTree package
Подмножество библиотеки 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 и объектной моделью документа (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-элемент поддерживает некоторые методы доступа, похожие на словарные и на списковые. Словарные операции используются для доступа к значениям атрибутов, а списковые – для доступа к дочерним узлам.
Операция |
Результат |
|---|---|
|
Возвращает n-й дочерний элемент. |
|
Возвращает список дочерних элементов с m-го по n-й. |
|
Возвращает количество дочерних элементов. |
|
Возвращает список дочерних элементов. |
|
Добавляет elem2 как дочерний элемент. |
|
Вставляет elem2 в указанную позицию. |
|
Удаляет n-й дочерний элемент. |
|
Возвращает список имён атрибутов. |
|
Возвращает значение атрибута name. |
|
Устанавливает новое значение для атрибута 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. Пожалуйста, прочитайте официальную документацию пакета для получения более подробной информации.
См. также
- https://web.archive.org/web/20201124024954/http://effbot.org/zone/element-index.htm
Официальная документация для ElementTree.
Пакет hashlib¶The hashlib package
Новый модуль hashlib, написанный Gregory P. Smith, был добавлен для
замены модулей md5 и sha. hashlib добавляет поддержку
дополнительных безопасных хэшей (SHA-224, SHA-256, SHA-384 и SHA-512). При
наличии модуль использует OpenSSL для быстрых оптимизированных под платформу реализаций
алгоритмов.
Старые модули md5 и sha всё ещё существуют как обёртки вокруг hashlib
для сохранения обратной совместимости. Интерфейс нового модуля очень близок
к интерфейсу старых модулей, но не идентичен. Наиболее существенное отличие
заключается в том, что функции-конструкторы для создания новых хэширующих объектов называются
по-другому.
# Старые версии
h = md5.md5()
h = md5.new()
# Новая версия
h = hashlib.md5()
# Старые версии
h = sha.sha()
h = sha.new()
# Новая версия
h = hashlib.sha1()
# Хэши, которые ранее были недоступны
h = hashlib.sha224()
h = hashlib.sha256()
h = hashlib.sha384()
h = hashlib.sha512()
# Альтернативная форма
h = hashlib.new('md5') # Указать алгоритм в виде строки
После создания хэш-объекта его методы остаются теми же:
update(string) хэширует указанную строку в текущее состояние дайджеста,
digest() и hexdigest() возвращают значение дайджеста в виде двоичной
строки или строки шестнадцатеричных цифр, а copy() возвращает новый хэширующий объект
с тем же состоянием дайджеста.
См. также
Документация для модуля hashlib.
Пакет sqlite3¶The sqlite3 package
Модуль pysqlite (https://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.
См. также
- https://www.pysqlite.org
Веб-страница pysqlite.
- https://www.sqlite.org
Веб-страница SQLite; документация описывает синтаксис и доступные типы данных для поддерживаемого диалекта SQL.
Документация по модулю sqlite3.
- PEP 249 – спецификация API баз данных 2.0
PEP написан Марком-Андре Лембургом.
Пакет wsgiref¶The 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()
См. также
- https://web.archive.org/web/20160331090247/http://wsgi.readthedocs.org/en/latest/
Центральный веб-сайт с ресурсами, связанными с WSGI.
- PEP 333 - Python Web Server Gateway Interface v1.0
PEP написан Филиппом Дж. Эби.
Изменения в процессе сборки и в C API¶Build and C API Changes
Изменения в процессе сборки Python и в C API включают:
Дерево исходного кода Python было перенесено из CVS в Subversion в ходе сложной процедуры миграции, которую курировал и безупречно выполнил Martin von Löwis. Эта процедура была разработана как PEP 347.
Компания Coverity, которая продаёт инструмент анализа исходного кода Prevent, предоставила результаты проверки исходного кода Python. Анализ выявил около 60 ошибок, которые были быстро исправлены. Многие из ошибок были проблемами подсчёта ссылок, часто возникавшими в коде обработки ошибок. Статистику см. на 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объявляет функцию как возвращающую значение указанного типа и использует квалификатор быстрого вызова.Py_LOCAL_INLINEделает то же самое, а также запрашивает встраивание функции. Если макросPY_LOCAL_AGGRESSIVEопределён до включенияpython.h, для модуля включается набор более агрессивных оптимизаций; следует провести бенчмаркинг, чтобы выяснить, действительно ли эти оптимизации ускоряют код. (Автор: Fredrik Lundh на спринте 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.5¶Porting 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.