contextlib — Утилиты для контекстов оператора with
В версии 2.5.
Исходный код: Lib/contextlib.py
Этот модуль предоставляет утилиты для общих задач, связанных с оператором with. Дополнительную информацию можно найти также в Типы менеджеров контекста и Менеджеры контекста оператора With.
Предоставляемые функции:
-
contextlib.contextmanager(func) -
Эта функция — декоратор, который может использоваться для определения фабричной функции для менеджеров контекста оператора
withбез необходимости создания класса или разделения методов__enter__()и__exit__().Хотя многие объекты изначально поддерживают использование в операторах with, иногда необходимо управлять ресурсом, который сам по себе не является менеджером контекста и не реализует метод
close()для использования сcontextlib.closing.Следующий абстрактный пример демонстрирует, как обеспечить правильное управление ресурсами:
from contextlib import contextmanager @contextmanager def managed_resource(*args, **kwds): # Code to acquire resource, e.g.: resource = acquire_resource(*args, **kwds) try: yield resource finally: # Code to release resource, e.g.: release_resource(resource) >>> with managed_resource(timeout=3600) as resource: ... # Resource is released at the end of this block, ... # even if code in the block raises an exceptionДекорируемая функция должна возвращать итератор-генератор при вызове. Этот итератор должен возвращать ровно одно значение, которое будет привязано к целевым переменным в блоке оператора
withв части с клаузойas, если таковая имеется.В точке, где генератор возвращает значение, выполняется блок, вложенный в оператор
with. Затем генератор возобновляется после выхода из блока. Если в блоке возникнет необработанное исключение, оно будет повторно поднято внутри генератора в точке, где произошел возврат значения. Таким образом, вы можете использовать операторtry…except…finallyдля перехвата ошибки (если таковая имеется) или обеспечения выполнения некоторой очистки. Если исключение перехватывается только для его регистрации или выполнения какого-либо действия (а не для полного подавления), генератор должен повторно поднять это исключение. В противном случае менеджер контекста генератора укажет операторуwith, что исключение обработано, и выполнение продолжится с инструкции, следующей непосредственно за операторомwith.
-
contextlib.nested(mgr1[, mgr2[, ...]]) -
Объединение нескольких менеджеров контекста в один вложенный менеджер контекста.
Эта функция устарела и рекомендуется в пользу использования нескольких менеджеров в операторе
with.Единственным преимуществом этой функции перед использованием нескольких менеджеров в операторе
withявляется возможность использования распаковки аргументов для работы с переменным числом менеджеров контекста, как показано ниже:from contextlib import nested with nested(*managers): do_something()Обратите внимание, что если метод
__exit__()одного из вложенных менеджеров контекста указывает на то, что исключение должно быть подавлено, никакая информация об исключении не будет передана остальным внешним менеджерам контекста. Аналогично, если метод__exit__()одного из вложенных менеджеров генерирует исключение, предыдущее состояние исключения будет утеряно; новое исключение будет передано методам__exit__()оставшихся внешних менеджеров контекста. В общем случае, методы__exit__()должны избегать генерации исключений, и, в частности, не должны повторно генерировать переданное исключение.Эта функция имеет два основных недостатка, которые привели к её устареванию. Во-первых, поскольку все менеджеры контекста создаются до вызова функции, методы
__new__()и__init__()внутренних менеджеров контекста фактически не попадают под область действия внешних менеджеров контекста. Это означает, что, например, использованиеnested()для открытия двух файлов является программно ошибочным, так как первый файл не будет закрыт немедленно, если при открытии второго файла возникает исключение.Во-вторых, если метод
__enter__()одного из внутренних менеджеров контекста генерирует исключение, которое перехватывается и подавляется методом__exit__()одного из внешних менеджеров контекста, эта конструкция сгенерируетRuntimeError, а не пропустит тело оператораwith.Разработчики, которым необходимо поддерживать вложенность переменного числа менеджеров контекста, могут либо использовать модуль
warningsдля подавления DeprecationWarning, генерируемого этой функцией, либо использовать эту функцию как модель для собственной реализации.Устарело начиная с версии 2.7: Теперь оператор with напрямую поддерживает эту функциональность (без путаницы и проблем с ошибками).
-
contextlib.closing(thing) -
Возвращает менеджер контекста, который закрывает thing по завершении блока. Это в основном эквивалентно:
from contextlib import contextmanager @contextmanager def closing(thing): try: yield thing finally: thing.close()И позволяет вам писать код, подобный этому:
from contextlib import closing import urllib with closing(urllib.urlopen('http://www.python.org')) as page: for line in page: print lineбез необходимости явного закрытия
page. Даже если произойдет ошибка,page.close()будет вызван при выходе из блокаwith.
© 2001–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/2.7/library/contextlib.html