Что такое контекстный менеджер
В питоне есть оператор with
. Размещенный внутри код выполняется с особенностью: до и после гарантированно срабатывают события входа в блок with
и выхода из него. Объект, который определяет эту логику, называется контекстным менеджером.
События входа и выхода из блока определены методами __enter__
и __exit__
. Первый срабатывает в тот момент, когда ход исполнения программы переходит внутрь with
. Метод может вернуть значение. Оно будет доступно низлежащему внутри блока with
коду.
__exit__
срабатывает в момент выхода из блока, в т.ч. и по причине исключения. В этом случае в метод будет передана тройка значений (exc_class, exc_instance, traceback)
.
Самый распространённый контекстный менеджер – класс, порожденный функцией open
. Он гарантирует, что файл будет закрыт даже в том случае, если внутри блока возникнет ошибка.
Нужно стараться выходить из контекстного менеджера как можно быстрее, чтобы освобождать контекст и ресурсы.
with open('file.txt') as f:
data = f.read()
process_data(data)
Пример реализации своего контекстного менеджера на основе класса:
class Printable:
def __enter__(self):
print('enter')
def __exit__(self, type, value, traceback):
print('exit')
Пример реализации своего контекстного менеджера с использованием встроенной библиотеки contextlib
from contextlib import contextmanager
@contextmanager
def printable():
print('enter')
try:
yield
finally:
print('exit')
Контекстные менеджеры также можно использовать для временной замены параметров, переменных окружения, транзакций БД.
Oct. 10, 2023, Источник
Это конструкция with
, которая предоставляет управление к доступу к некому ресурсу.
На контекстный менеджер возлагается 2 функции:
- Что нужно сделать в момент когда необходим доступ к ресурсу
- Что нужно сделать когда доступ уже не нужен
Встроенная функция open открывает и закрывает объект
Контекстные менеджеры упрощают запись блоков try-finally
. Оператор with
позволяет разработчикам писать свой код в сжатом и понятном виде.
Пример менеджера контекста для открытия файла
class FileManager:
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
self.file = None
def __enter__(self):
try:
self.file = open(self.filename, self.mode)
return self.file
except FileNotFoundError:
print("Error: File not found")
raise
def __exit__(self, exc_type, exc_val, exc_tb):
if self.file:
self.file.close()
with FileManager("test.txt", "r") as f:
if f:
print(f.read())
Oct. 10, 2023, Источник
Менеджер контекста позволяет выделять и освобождать ресурсы строго по необходимости. В Python за это отвечает блок с оператором with
. Он имеет следующую конструкцию:
[async] with <функция> as <переменная>:
...
Протокол контекстного менеджера¶
Контекстный менеджер должен иметь следующие методы:
- Если он синхронный -
__enter__
и__exit__
- Если асинхронный -
__aenter__
и__aexit__
В дальнейшем речь будет идти про синхронный контекстный менеджер, но ничего не мешает всё что указано ниже использовать с асинхронным контекстным менеджером (если не указано иное).
Обработка исключений¶
В случае возникновения исключения в метод __exit__
передается 3 параметра - type
, value
и traceback
.
При обработке исключений важно то, что возвращает метод __exit__
. Тут есть 2 варианта:
- В случае, если исключение было обработано нормально метод должен вернуть True.
- Возращение любого другого значения возбудит исключение, которое передадится на уровень выше.
Контекстный менеджер из генератора¶
Здесь на помощь к нам приходит contextlib
. С помощью contextmanager
мы можем реализовать менеджер контекста через декоратор и генераторы. Выглядит это так:
from contextlib import contextmanager
@contextmanager
def open_file(name):
f = open(name, 'w')
yield f
f.close()
Работает это следующим образом:
- Python встречает ключевое слово yield, из-за чего создается генератор, а не функция. Генератор должен возвращать только одно значение, оно будет привязано к with.
- Тот в свою очередь реализует методы
__enter__
и__exit__
. Всё что до использования генератора попадает в__enter__
, а после него - в__exit__
- В случае возникновения исключения оно вызывается внутри генератора, поэтому можно его словить и обработать при помощи конструкции
`try ... except ...
Для асинхронных функций нужно использовать asynccontextmanager
из того же contextlib
Oct. 24, 2023, notes.kiriha.ru
Примеры ответов:
- Tech Interview Fest | Моковое собесе…
- Собеседование на позицию Senior Pyth…
- Собеседование на позицию Backend Dev…
- Собеседование на позицию Backend Dev…
- Запись интервью на позицию "Сениора"
- Собеседование Trainee Python Develop…
- Собеседование Trainee Python Develop…
- Собеседование Trainee Python Develop…
- Собеседование Python 2023. Разбор ба…
- Собеседование Python developer на 30…
- luchanos | Balabot IT LIVE | Собесед…
- luchanos | Balabot IT LIVE | Собесед…
- 15 теоретических вопросов для начина…