Как стать автором
Обновить

Комментарии 9

Сюда можно добавить про библиотеку contextlib с декоратором contextmanager.

Нет необходимости писать класс для нового контекстного менеджера, достаточно обернуть генератор в декоратор @contextmanager. Ссылка на доку: contextlib — Utilities for with-statement contexts

Пример из документации:

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

Там много ещё чего.

Я думаю это можно вообще в отдельную статью можно вынести.

class AsyncTimer:

def __enter__(self):

async def __aexit__(self, exc_type, exc_val, exc_tb):


С такой комбинацией дандеров это в принципе не контекст менеджер.

Спасибо, поправил.

В парсерах часто использую где нужно подтягивать селениум. Штука тяжелая, потому от лишних экземпляров стоит сразу избавляться.

А вы не могли бы более подробно объяснить, что делает вот этот код?

with threading.Lock() as lock:
    # Блокировка ресурса перед выполнением задачи
    lock.acquire()
    try:
        t = threading.Thread(target=worker)
        t.start()
    finally:
        # Освобождение ресурса после выполнения задачи
        lock.release()

Он не работает.

  1. lock в данном случае содержит результат блокировки, а сам лок

  2. Если бы там был все таки Лок, мы бы получили двойную блокировку (одна из-за контекстного менеджера, вторая из-за aquire)

  3. Если бы мы взяли RLock вместо Lock, это позволило бы внутри одного контекста повторно вызвать aquire, но код бы все равно не имел смысла, потому что Лок используется только в одном потоке

Метод для предоставления асинхронного контекста называется __aenter__

P.s.: порой кажется, что статьи здесь пишутся абы как, так ещё и редакторы их вообще не смотрят

Как-то очень вскользь сказано про обработку исключений. Хотя это, в сущности, первое, для чего были изначально предназначены контекстные менеджеры - удобная обертка над try ... finally.

Суть контекстного менеджера в том, что в констукции with гарантируется, что если метод __enter__() был выполнен без ошибок, то метод __exit__() будет вызван всегда. Закрытие файлов, соединений и т. п. финализирующие операции - это только примеры того, что может потребоваться сделать при выходе контекста. А выходим мы из контекста либо после выполнения всех операци в блоке with. Тогда в качестве параметров в метод __exit__ передаетя три значения None. Либо если в блоке with возникает необработанное исключение. Тогда в __exit__ попадает информмация об этом исключении в виде 3 параметров, которые представляют собой ничто иное как кортеж значений, возвращаемых функцией sys.exc_info(), будучи вызванной внутри блока finally.

Внутри __exit__ исключение можно обработать или передать выше. Если __exit__ возвращает любое истинное значение, тогда исключение считается обработанным, и выполнение кода продолжается с места выхода из контекстного менеджера. Если __exit__ возвращает ложное значение, например None, то при выходе из метода исключение будет обрабатываться обычным образом. При этом стоит помнить, что новые исключения, возникшие в ходе выполнения метода __exit__, всегда замещают исключения, которые могли возникнуть в ходе выполнения тела with и попали в параметры метода __exit__.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории