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