> **Источник:** https://python-all.ru/3.0/library/contextlib.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

# `contextlib` – Утилиты для контекстов оператора [`with`](https://python-all.ru/3.0/reference/compound_stmts.html#with).

Этот модуль предоставляет утилиты для типичных задач, связанных с оператором [`with`](https://python-all.ru/3.0/reference/compound_stmts.html#with). Дополнительную информацию см. также в разделах [*Типы менеджеров контекста*](https://python-all.ru/3.0/library/stdtypes.html#typecontextmanager) и [*Менеджеры контекста оператора with*](https://python-all.ru/3.0/reference/datamodel.html#context-managers).

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

#### `[contextlib.contextmanager]contextlib.contextmanager(func)`

Эта функция – [*декоратор*](https://python-all.ru/3.0/glossary.html#term-decorator), который можно использовать для определения фабричной функции для менеджеров контекста оператора [`with`](https://python-all.ru/3.0/reference/compound_stmts.html#with), без необходимости создавать класс или отдельные методы [`__enter__()`](https://python-all.ru/3.0/reference/datamodel.html#object.__enter__) и [`__exit__()`](https://python-all.ru/3.0/reference/datamodel.html#object.__exit__).

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

```python
from contextlib import contextmanager

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

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

Декорируемая функция при вызове должна возвращать [*генератор*](https://python-all.ru/3.0/glossary.html#term-generator)-итератор. Этот итератор должен передать (yield) ровно одно значение, которое будет связано с целями в предложении [`as`](https://python-all.ru/3.0/reference/compound_stmts.html#as) оператора [`with`](https://python-all.ru/3.0/reference/compound_stmts.html#with), если оно есть.

В точке, где генератор выполняет yield, выполняется блок, вложенный в оператор [`with`](https://python-all.ru/3.0/reference/compound_stmts.html#with). Затем генератор возобновляется после выхода из блока. Если в блоке возникает необработанное исключение, оно повторно возбуждается внутри генератора в точке, где произошёл yield. Таким образом, можно использовать конструкцию [`try`](https://python-all.ru/3.0/reference/compound_stmts.html#try)...[`except`](https://python-all.ru/3.0/reference/compound_stmts.html#except)...[`finally`](https://python-all.ru/3.0/reference/compound_stmts.html#finally) для перехвата ошибки (если она есть) или для обеспечения выполнения очистки. Если исключение перехватывается лишь для того, чтобы залогировать его или выполнить какое-либо действие (а не подавить его полностью), генератор должен возобновить (reraise) это исключение. В противном случае менеджер контекста-генератор сообщит оператору [`with`](https://python-all.ru/3.0/reference/compound_stmts.html#with), что исключение обработано, и выполнение продолжится с оператора, непосредственно следующего за оператором [`with`](https://python-all.ru/3.0/reference/compound_stmts.html#with).

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

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

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

```python
from contextlib import nested

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

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

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

Note that if the [`__exit__()`](https://python-all.ru/3.0/reference/datamodel.html#object.__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__()`](https://python-all.ru/3.0/reference/datamodel.html#object.__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__()`](https://python-all.ru/3.0/reference/datamodel.html#object.__exit__) methods of any remaining outer context managers. In general, [`__exit__()`](https://python-all.ru/3.0/reference/datamodel.html#object.__exit__) methods should avoid raising exceptions, and in particular they should not re-raise a passed-in exception.

#### `[contextlib.closing]contextlib.closing(thing)`

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

```python
from contextlib import contextmanager

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

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

```python
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`](https://python-all.ru/3.0/reference/compound_stmts.html#with).

> **См. также**
>
> **[**PEP 0343**](https://python-all.ru/3.0/library/contextlib.html) – оператор «with»**
>
> Спецификация, предыстория и примеры для оператора
>
> [`with`](https://python-all.ru/3.0/reference/compound_stmts.html#with)
>
> в Python.
