Документация Python неофициальный перевод

contextlib – Утилиты для контекстов оператора with.contextlib – Utilities for with-statement contexts.

Этот модуль предоставляет утилиты для типичных задач, связанных с оператором with. Дополнительную информацию см. также в разделах Типы менеджеров контекста и Менеджеры контекста оператора with.

Предоставляемые функции:

contextlib.contextmanager(func)

Эта функция – декоратор, который можно использовать для определения фабричной функции для менеджеров контекста оператора with, без необходимости создавать класс или отдельные методы __enter__() и __exit__().

Простой пример (это не рекомендуется как реальный способ генерации HTML!):

from contextlib import contextmanager

@contextmanager
def tag(name):
    print("<%s>" % name)
    yield
    print("</%s>" % name)

>>> with tag("h1"):
...    print("foo")
...
<h1>
foo
</h1>

Декорируемая функция при вызове должна возвращать генератор-итератор. Этот итератор должен передать (yield) ровно одно значение, которое будет связано с целями в предложении as оператора with, если оно есть.

В точке, где генератор выполняет yield, выполняется блок, вложенный в оператор with. Затем генератор возобновляется после выхода из блока. Если в блоке возникает необработанное исключение, оно повторно возбуждается внутри генератора в точке, где произошёл yield. Таким образом, можно использовать конструкцию try...except...finally для перехвата ошибки (если она есть) или для обеспечения выполнения очистки. Если исключение перехватывается лишь для того, чтобы залогировать его или выполнить какое-либо действие (а не подавить его полностью), генератор должен возобновить (reraise) это исключение. В противном случае менеджер контекста-генератор сообщит оператору with, что исключение обработано, и выполнение продолжится с оператора, непосредственно следующего за оператором with.

contextlib.nested(mgr1[, mgr2[, ...]])

Объединяет несколько менеджеров контекста в один вложенный менеджер контекста.

Пример такого кода:

from contextlib import nested

with nested(A, B, C) as (X, Y, Z):
    do_something()

эквивалентен следующему:

with A as X:
    with B as Y:
        with C as Z:
            do_something()

Note that if the __exit__() method of one of the nested context managers indicates an exception should be suppressed, no exception information will be passed to any remaining outer context managers. Similarly, if the __exit__() method of one of the nested managers raises an exception, any previous exception state will be lost; the new exception will be passed to the __exit__() methods of any remaining outer context managers. In general, __exit__() methods should avoid raising exceptions, and in particular they should not re-raise a passed-in exception.

contextlib.closing(thing)

Возвращает контекстный менеджер, который закрывает thing после завершения блока. По сути эквивалентно следующему:

from contextlib import contextmanager

@contextmanager
def closing(thing):
    try:
        yield thing
    finally:
        thing.close()

И позволяет писать код следующим образом:

from contextlib import closing
from urllib.request import urlopen

with closing(urlopen('http://www.python.org')) as page:
    for line in page:
        print(line)

без необходимости явно закрывать page. Даже если произойдёт ошибка, page.close() будет вызван при выходе из блока with.

См. также

PEP 0343 – оператор «with»
Спецификация, предыстория и примеры для оператора with в Python.