Что нового в 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: Утверждение «with»). Значения теперь можно передавать в генераторы (раздел PEP 342: Новые возможности генератора). Импорт теперь отображается как абсолютный, так и относительный (раздел PEP 328: Абсолютный и относительный импорт). Некоторые основные случаи обработки исключений обрабатываются лучше (раздел PEP 341: Единая попытка/исключение/окончательно). Все эти улучшения имеют смысл, но они являются улучшениями той или иной конкретной языковой функции; ни одно из них не является существенным изменением семантики 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
Вычисление по-прежнему выполняется медленно, как и в существующих логических выражениях, поэтому порядок вычисления немного меняется. Выражение condition в середине вычисляется первым, а выражение true_value вычисляется только в том случае, если условие было истинным. Аналогично, выражение false_value вычисляется только в том случае, если условие равно false.
Этот синтаксис может показаться странным и задним числом; почему условие помещается в середину выражения, а не в начало, как в C c ? x : y
? Решение было проверено путем применения нового синтаксиса к модулям стандартной библиотеки и просмотра того, как читается полученный код. Во многих случаях, когда используется условное выражение, одно значение, по-видимому, является «обычным случаем», а другое - «исключительным случаем», используемым только в редких случаях, когда условие не выполняется. Условный синтаксис делает этот шаблон немного более очевидным:
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 версии 1.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 версии 1.1
PEP предложен и написан А.М. Кухлингом, Ричардом Джонсом и Фредом Дрейком; реализован Ричардом Джонсом и Фредом Дрейком.
PEP 328: Абсолютный и относительный импорт¶
Более простая часть PEP 328 была реализована в Python 2.4: теперь можно использовать круглые скобки для заключения имен, импортированных из модуля с помощью инструкции from ... import ...
, что упрощает импорт множества различных имен.
Более сложная часть была реализована в Python 2.5: при импорте модуля можно указать, что он использует абсолютный импорт или импорт, относящийся к пакету. Планируется, что в будущих версиях Python абсолютный импорт будет использоваться по умолчанию.
Допустим, у вас есть такой каталог пакетов, как этот:
pkg/
pkg/__init__.py
pkg/main.py
pkg/string.py
Это определяет пакет с именем pkg
, содержащий подмодули pkg.main
и pkg.string
.
Рассмотрим код в модуле main.py
. Что произойдет, если он выполнит инструкцию import string
? В Python 2.4 и более ранних версиях сначала выполняется поиск в каталоге пакета для выполнения относительного импорта, находит pkg/string.py
, импортирует содержимое этого файла как модуль pkg.string
, и этот модуль привязывается к имени string
в пространстве имен модуля pkg.main
.
Это нормально, если вы хотели pkg.string
. Но что, если вам нужен стандартный модуль string
для Python? Не существует простого способа игнорировать pkg.string
и искать стандартный модуль; как правило, вам приходилось просматривать содержимое sys.modules
, которое немного нечетко. Пакет Holger Krekel 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, написанный Аазом; реализован Томасом Ваутерсом.
- 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: Единая попытка/исключение/окончательно¶
До версии 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
, выполняется обработчик-1; в противном случае, если оно относится к классу Exception2
, обработчик-2 выполняется и так далее. Если исключение не возникает, выполняется else-block.
Независимо от того, что произошло ранее, final-block выполняется после завершения блока кода и обработки всех возникших исключений. Даже если в обработчике исключений или в else-block произошла ошибка и возникло новое исключение, код в final-block все равно выполняется.
См.также
- 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
генератора всегда был объект 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»¶
Оператор „with
разъясняет код, который ранее использовал блоки try...finally
для обеспечения выполнения кода очистки. В этом разделе я обсудим этот оператор в том виде, в каком он будет часто использоваться. В следующем разделе я рассмотрю детали реализации и покажу, как писать объекты для использования с этим оператором.
Оператор „with
“ представляет собой новую структуру потока управления, базовая структура которой:
with expression [as variable]:
with-block
Вычисляется выражение, и в результате должен быть создан объект, поддерживающий протокол управления контекстом (то есть имеющий методы __enter__()
и __exit__()
).
Объект __enter__()
вызывается перед выполнением with-block и, следовательно, может запускать установочный код. Он также может возвращать значение, привязанное к имени переменной, если оно задано. (Внимательно обратите внимание, что переменной не присваивается результат выражения.)
После завершения выполнения with-block вызывается метод объекта __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 вызывает исключение, вызывается
__exit__(type, value, traceback)
с подробными сведениями об исключении, теми же значениями, которые возвращаетsys.exc_info()
. Возвращаемое методом значение определяет, будет ли повторно вызвано исключение: любое значение false повторно вызовет исключение, и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__()
довольно прост, достаточно только запустить новую транзакцию. Для этого приложения результирующий объект cursor был бы полезным результатом, поэтому метод вернет его. Затем пользователь может добавить 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__()
, а полученное значение будет возвращаемым методом, которое будет привязано к переменной в инструкции „with
“ as
оговорка, если таковая имеется. Код, следующий за 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: Исключения как классы нового стиля¶
Классы исключений теперь могут быть классами нового стиля, а не только классическими классами, а встроенный класс 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
прямо сейчас. Было высказано предположение, что в Python 3.0 следует удалить пустую форму except:
, но Гвидо ван Россум еще не решил, делать это или нет.
Использование строк в качестве исключений, как в инструкции raise "Error occurred"
, устарело в Python 2.5 и вызовет предупреждение. Цель состоит в том, чтобы иметь возможность удалить функцию исключения строк в нескольких версиях.
См.также
- PEP 352 - Обязательный суперкласс для исключений
PEP написан Бреттом Кэнноном и Гвидо ван Россумом; реализован Бреттом Кэнноном.
PEP 353: Использование ssize_t в качестве типа индекса¶
Масштабное изменение C API Python с использованием нового определения типа Py_ssize_t
вместо int позволит интерпретатору обрабатывать больше данных на 64-разрядных платформах. Это изменение не влияет на производительность Python на 32-разрядных платформах.
Различные части интерпретатора Python использовали тип C int для хранения размеров или количества; например, количество элементов в списке или кортеже сохранялось в виде int. Компиляторы C для большинства 64-разрядных платформ по-прежнему определяют int как 32-разрядный тип, что означает, что списки могут содержать только 2**31 - 1
= 2147483647 элементов. (На самом деле существует несколько различных моделей программирования, которые могут использовать 64-разрядные компиляторы C - см. https://unix.org/version2/whatsnew/lp64_wp.html для обсуждения - но наиболее распространенная модель оставляет: c:expr: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__()
. При использовании записи фрагментов, как в [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
был добавлен в структуру C-level PyNumberMethods
, чтобы позволить расширениям C реализовать этот протокол. PyNumber_Index(obj)
может использоваться в коде расширения для вызова функции __index__()
и получения ее результата.
См.также
- PEP 357 - Позволяет использовать любой объект для нарезки
PEP, написанный и реализованный Трэвисом Олифантом.
Другие языковые изменения¶
Вот все изменения, которые Python 2.5 вносит в основной язык Python.
В типе
dict
добавлена новая функция, позволяющая подклассам предоставлять значение по умолчанию, когда ключ не содержится в словаре. Когда ключ не найден, будет вызван метод dictionary__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-разрядных строках, так и в Юникоде есть новые методы
partition(sep)
иrpartition(sep)
, которые упрощают общий вариант использования.Метод
find(S)
часто используется для получения индекса, который затем используется для разрезания строки и получения фрагментов, которые находятся до и после разделителя.partition(sep)
объединяет этот шаблон в один вызов метода, который возвращает кортеж из 3 элементов, содержащий подстроку перед разделителем, сам разделитель и подстрока после разделителя. Если разделитель не найден, то первым элементом кортежа будет вся строка целиком, а два других элемента будут пустыми.rpartition(sep)
также возвращает кортеж из 3 элементов, но начинает поиск с конца строки;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()
типов string теперь принимают кортежи строк для проверки.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
, если любое значение, возвращаемое итератором, равно true; в противном случае оно вернетFalse
.all()
возвращаетTrue
только в том случае, если все значения, возвращаемые итератором, оцениваются как 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
. По умолчанию это предупреждение игнорируется автоматически; укажите параметр-Wd
при запуске исполняемого файла Python, чтобы отобразить предупреждающее сообщение. (Реализовано Томасом Ваутерсом).Список базовых классов в определении класса теперь может быть пустым. Например, теперь это разрешено:
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 sprint, проходившем в Рейкьявике, Исландия, с 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 sprint.)Модуль
re
получил ускорение на 1 или 2%, переключившись на функции распределителя Python вместо системныхmalloc()
иfree()
. (Автор: Джек Дидерих из NeedForSpeed sprint.)Оптимизатор peephole в генераторе кода теперь выполняет простое сворачивание констант в выражениях. Если вы напишете что-то вроде
a = 2+3
, генератор кода выполнит арифметические действия и выдаст код, соответствующийa = 5
. (Предложено и реализовано Раймондом Хеттингером.)Вызовы функций теперь выполняются быстрее, поскольку объекты кода теперь сохраняют последний завершенный кадр («зомби-кадр») во внутреннем поле объекта кода, повторно используя его при следующем вызове объекта кода. (Оригинальный патч Майкла Хадсона, доработанный Армином Риго и Ричардом Джонсом; был добавлен в ходе NeedForSpeed sprint.) Объекты Frame также немного уменьшились в размерах, что может улучшить локализацию кэша и немного сократить использование памяти. (Автор - Нил Норвиц).
Встроенные в Python исключения теперь представляют собой классы нового стиля, что значительно ускоряет создание экземпляров. Таким образом, обработка исключений в Python 2.5 примерно на 30% быстрее, чем в версии 2.4. ((Вклад Ричарда Джонса, Георга Брандла и Шона Райфшнайдера в NeedForSpeed sprint.)
Импорт теперь кэширует опробованные пути, записывая, существуют ли они или нет, чтобы интерпретатор делал меньше
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)
, который удаляет первое вхождение value в очередь, вызываяValueError
, если значение не указано в очереди.не найден. (Автор - Раймонд Хеттингер.)Новый модуль: Модуль
contextlib
содержит вспомогательные функции для использования с новой инструкцией „with
. Подробнее об этом модуле смотрите в разделе Модуль contextlib.Новый модуль: Модуль
cProfile
является реализацией на языке Си существующего модуля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
newfileno()
возвращает файловый дескриптор для текущего открытого файла. (Автор: Георг Брандл.)В модуле
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
в качестве аргументов start и step. Это делает ее более совместимой с атрибутами объектов 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 в рамках программы Summer of Code 2005.)
Новый модуль: модуль
msilib
позволяет создавать файлы установщика Microsoft.msi
и CAB-файлы. Также включена некоторая поддержка чтения базы данных.msi
. (Автор - Мартин фон Левис).Модуль
nis
теперь поддерживает доступ к доменам, отличным от системного домена по умолчанию, путем предоставления аргумента domain функциямnis.match()
иnis.maps()
. (Автор - Бен Белл).Функции модуля
operator
itemgetter()
иattrgetter()
теперь поддерживают несколько полей. Вызов, такой какoperator.attrgetter('a', 'b')
, вернет функцию, которая извлекает атрибутыa
иb
. Сочетание этой новой функции с параметромsort()
методаkey
позволяет легко сортировать списки, используя несколько полей. (Автор - Раймонд Хеттингер).Модуль
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()
не принимает идентификатор процесса в качестве входных данных, поэтому ожидает завершения любого дочернего процесса и возвращает 3 кортежа из process-id, exit-status, resource-usage, возвращенных из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. (Автор: Phillip J. Eby.)Пакет тестов pybench от Марка-Андре Лембурга не включен в каталог
Tools/pybench
. Пакет pybench suite является усовершенствованием широко используемой программыpystone.py
, поскольку pybench обеспечивает более детальное измерение скорости интерпретатора. Он рассчитывает время выполнения определенных операций, таких как вызовы функций, разбиение кортежей, поиск методов и числовые операции, вместо того, чтобы выполнять множество различных операций и сводить результат к одному числу, как это делаетpystone.py
.Модуль
pyexpat
теперь использует синтаксический анализатор Expat версии 2.0. (Автор - Трент Мик).Класс
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, благодаря патчу от Philippe Biondi. Сокеты Netlink - это специфичный для Linux механизм обмена данными между процессом в пользовательском пространстве и кодом ядра; вводная статья о них находится по адресу https://www.linuxjournal.com/article/7356. В коде Python адреса netlink представлены в виде кортежа из 2 целых чисел,(pid, group_mask)
.Два новых метода для объектов socket,
recv_into(buffer)
иrecvfrom_into(buffer)
, сохраняют полученные данные в объекте, поддерживающем протокол 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)
Вы также можете напрямую загружать и распаковывать данные в объекты buffer и из них, используя методы
pack_into(buffer, offset, v1, v2, ...)
иunpack_from(buffer, offset)
. Это позволяет сохранять данные непосредственно в массиве или файле, отображаемом в памяти.(
Struct
объекты были реализованы Бобом Ипполито в Need For Speed sprint. Поддержка буферных объектов была добавлена Мартином Блейсом, также в NeedForSpeed sprint.)Разработчики Python перешли с CVS на Subversion в процессе разработки версии 2.5. Информация о точной версии сборки доступна в виде переменной
sys.subversion
, состоящей из 3 кортежей(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()
, возвращает текущие стековые фреймы для всех запущенных потоков в виде словаря, сопоставляющего идентификаторы потоков с самым верхним стековым фреймом, который в данный момент активен в этом потоке на момент вызова функции. (Автор: Тим Питерс).Класс
TarFile
в модулеtarfile
теперь имеет методextractall()
, который извлекает все элементы из архива в текущий рабочий каталог. Также можно указать другой каталог в качестве объекта извлечения и распаковать только часть элементов архива.Сжатие, используемое для файла tarf, открытого в потоковом режиме, теперь может быть автоматически определено с помощью режима
'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_int()
, c_float()
, c_double()
, c_char_p()
(эквивалентно : c:expr: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)
Предполагается, что функции языка Си возвращают целые числа, но вы можете установить атрибут restype
объекта function, чтобы изменить это:
>>> 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
входит в состав core Python.
См.также
- https://web.archive.org/web/20180410025338/http://starship.python.net/crew/theller/ctypes/
Веб-страница, предшествующая stdlib, содержит руководство, ссылки и часто задаваемые вопросы.
Документация к модулю 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 от объектной модели документа; в 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()
, он может принимать либо строку, либо объект, подобный файлу:
# 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()
и hexdigest()
возвращают значение дайджеста в виде двоичной строки или строки из шестнадцатеричные цифры, а copy()
возвращает новый объект хэширования с тем же состоянием дайджеста.
См.также
Документация к модулю hashlib
.
Пакет sqlite3¶
Модуль pysqlite (https://www.pysqlite.org), являющийся оболочкой для встроенной базы данных SQLite, был добавлен в стандартную библиотеку под именем пакета sqlite3
.
SQLite - это библиотека на языке Си, которая предоставляет облегченную дисковую базу данных, не требующую отдельного серверного процесса и позволяющую обращаться к базе данных с использованием нестандартного варианта языка запросов SQL. Некоторые приложения могут использовать SQLite для внутреннего хранения данных. Также можно создать прототип приложения с помощью SQLite, а затем перенести код в более крупную базу данных, такую как PostgreSQL или Oracle.
pysqlite был написан Герхардом Херингом и предоставляет интерфейс SQL, совместимый со спецификацией DB-API 2.0, описанной в PEP 249.
Если вы компилируете исходный код Python самостоятельно, обратите внимание, что дерево исходных текстов не содержит код SQLite, а только модуль-оболочку. Перед компиляцией Python вам необходимо установить библиотеки и заголовки SQLite, а процесс сборки скомпилирует модуль, когда будут доступны необходимые заголовки.
Чтобы использовать модуль, вы должны сначала создать объект 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. Поместите ?
в качестве заполнителя везде, где вы хотите использовать значение, а затем укажите набор значений в качестве второго аргумента для метода cursor 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
БОДРЯЩИЙ настрой, написанный Марком-Андре Лембургом.
Пакет wsgiref¶
Интерфейс шлюза веб-сервера (WSGI) версии 1.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 версии 1.0
БОДРЯЩИЙ настрой, написанный Филиппом Дж. Эби.
Изменения в сборке и C API¶
Изменения в процессе сборки Python и в C API включают:
Дерево исходных текстов Python было преобразовано из CVS в Subversion в результате сложной процедуры миграции, которая контролировалась и безупречно выполнялась Мартином фон Левисом. Процедура была разработана как PEP 347.
Компания Coverity, которая продает инструмент для анализа исходного кода под названием Prevent, предоставила результаты своего анализа исходного кода Python. В ходе анализа было обнаружено около 60 ошибок, которые были быстро исправлены. Многие из ошибок были связаны с повторным подсчетом проблем, часто возникающих в коде обработки ошибок. Смотрите статистику https://scan.coverity.com.
Самое большое изменение в C API было внесено в PEP 353, которое изменяет интерпретатор, чтобы использовать определение типа : c:type: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, представляющий содержимое. Затем это действие можно преобразовать в объектный код с помощьюPyAST_Compile()
. Для получения дополнительной информации ознакомьтесь с исходным кодом, а затем задавайте вопросы по python-dev.Кодекс AST был разработан под руководством Джереми Хилтона и внедрен (в алфавитном порядке) Бреттом Кэнноном, Ником Когланом, Грантом Эдвардсом, Джоном Эресманом, Куртом Кайзером, Нилом Норвицем, Тимом Питерсом, Армином Риго и Нилом Шеменауэром, а также участниками ряда спринтов AST на таких конференциях, как ПиКон.
Был применен патч Эвана Джонса для obmalloc, впервые описанный в докладе на PyCon DC 2005. Python 2.4 разместил небольшие объекты в областях размером 256 КБ, но никогда не освобождал области. С помощью этого исправления Python освободит арены, когда они будут пусты. В результате на некоторых платформах, когда вы размещаете много объектов, использование памяти Python может фактически снизиться при их удалении, и память может быть возвращена операционной системе. (Реализовано Эваном Джонсом и переработано Тимом Питерсом.)
Обратите внимание, что это изменение означает, что модули расширения должны быть более осторожны при выделении памяти. API Python имеет множество различных функций для выделения памяти, которые сгруппированы в семейства. Например,
PyMem_Malloc()
,PyMem_Realloc()
иPyMem_Free()
являются одним семейством, которое выделяет необработанную память, в то время какPyObject_Malloc()
,PyObject_Realloc()
, иPyObject_Free()
- это еще одно семейство, которое предполагается использовать для создания объектов Python.Ранее все эти различные семейства сводились к функциям платформы
malloc()
иfree()
. Это означало, что не имело значения, если вы что-то неправильно поняли и выделили память с помощью функцииPyMem
, но освободили ее с помощью функцииPyObject
. С изменениями obmalloc в версии 2.5 эти семейства теперь работают по-разному, и несоответствия, вероятно, приведут к сбою сегмента. Вам следует тщательно протестировать свои модули расширения C с помощью Python 2.5.Встроенные типы наборов теперь имеют официальный C API. Вызовите
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"
. ( Автор: Barry Warsaw.)Два новых макроса могут быть использованы для указания функций C, которые являются локальными для текущего файла, что позволяет использовать соглашение о более быстром вызове.
Py_LOCAL(type)
объявляет функцию как возвращающую значение указанного типа и использует квалификатор быстрого вызова.Py_LOCAL_INLINE(type)
делает то же самое, а также запрашивает встроенную функцию. Если макросPY_LOCAL_AGGRESSIVE
определен до включенияpython.h
, для модуля включается набор более агрессивных оптимизаций; вам следует сравнить результаты, чтобы выяснить, действительно ли эти оптимизации ускоряют код. ((Автор: Фредрик Лунд из NeedForSpeed sprint.)PyErr_NewException(name, base, dict)
теперь может принимать кортеж базовых классов в качестве аргумента base. (Автор - Георг Брандл.)Функция
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);
Изменения, связанные с конкретным портом¶
Mac OS X (10.3 и выше): при динамической загрузке модулей теперь используется функция
dlopen()
вместо функций, специфичных для macOS.Mac OS X: в скрипт configure, который компилирует интерпретатор в виде универсального двоичного файла, способного работать как на процессорах PowerPC, так и на процессорах Intel, был добавлен параметр
--enable-universalsdk
. (Автор: Рональд Оуссорен; bpo-2573.)Windows:
.dll
больше не поддерживается в качестве расширения имени файла для модулей расширения..pyd
теперь это единственное расширение имени файла, которое будет использоваться для поиска.
Перенос на Python 2.5¶
В этом разделе перечислены ранее описанные изменения, которые могут потребовать внесения изменений в ваш код:
ASCII теперь является кодировкой по умолчанию для модулей. Теперь синтаксическая ошибка возникает, если модуль содержит строковые литералы с 8-разрядными символами, но не имеет описания кодировки. В Python 2.4 это вызвало предупреждение, а не синтаксическую ошибку.
Ранее атрибутом
gi_frame
генератора всегда был объект 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
или пустой кортеж отключает эту проверку пути.C API: Многие функции теперь используют : c:type:Py_ssize_t вместо int, что позволяет обрабатывать больше данных на 64-разрядных компьютерах. Возможно, потребуется внести те же изменения в код расширения, чтобы избежать предупреждений и поддерживать 64-разрядные компьютеры. Смотрите предыдущий раздел PEP 353: Использование ssize_t в качестве типа индекса для обсуждения этого изменения.
C API: Изменения в obmalloc означают, что вы должны быть осторожны и не смешивать использование семейств функций
PyMem_*
иPyObject_*
. Память, выделенная для одного семейства*_Malloc
, должна быть освобождена с помощью функции соответствующего семейства*_Free
.
Признание¶
Автор хотел бы поблагодарить следующих людей за предложения, исправления и помощь в работе над различными вариантами этой статьи: Георга Брандла, Ника Коглана, Филиппа Дж. Эби, Ларса Густабеля, Раймонда Хеттингера, Ральфа У. Гроссе-Кунстлеве, Кента Джонсона, Иэна Лоу, Мартина фон Левиса, Фредрика Лунда, Эндрю Макнамару., Скип Монтанаро, Густаво Нимейер, Пол Прескод, Джеймс Прайор, Майк Ровнер, Скотт Вайкарт, Барри Варшава, Томас Ваутерс.