Spec-Zone.ru › Python 2.7

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.

См. также

PEP 343 - Оператор «with»

Спецификация, контекст и примеры для оператора Python with.

© 2001–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/2.7/library/contextlib.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API