Как я могу поймать исключение внутри менеджера контекста?

У меня есть случай, когда мне нужно поймать какое-то исключение (в коде, например, я хочу поймать ZeroDivisionError) и обработать его внутри моего собственного контекстного менеджера. Мне нужно проверить количество этого исключения и сделать печать в консоли. Теперь, когда я запускаю свой код, я поймал ZeroDivisionError один раз, а затем

Traceback (most recent call last):
  File "/home/example.py", line 23, in foo
    a / b
ZeroDivisionError: division by zero

Process finished with exit code 1

Например:

class ExceptionCather:
    def __init__(
            self,
            try_counter,
            exc_type=None
    ):
        self.try_counter = try_counter

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc, tb):
        if exc_type == ZeroDivisionError:
            self.try_counter += 1
            if self.try_counter == 2:
                print(self.try_counter)


def foo(a, b):
    try_counter = 0
    while True:
        with ExceptionCather(try_counter):
            a / b


if __name__ == '__main__':
    foo(1, 0)

Как я могу поймать ошибку, сделать печать в консоли и продолжить свой скрипт? Будем признательны за помощь


person MrOldSir    schedule 19.03.2020    source источник


Ответы (1)


Я не уверен, чего вы хотите достичь, но если вы хотите обработать ZeroDivisionError, просто верните True из __exit__:

class ExceptionCather:
    def __init__(
            self,
            try_counter,
            exc_type=None
    ):
        self.try_counter = try_counter

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc, tb):
        if exc_type == ZeroDivisionError:
            self.try_counter += 1
            if self.try_counter == 2:
                print(self.try_counter)
            return True  # This will not raise `ZeroDivisonError`


def foo(a, b):
    try_counter = 0
    while True:
        with ExceptionCather(try_counter):
            a / b


if __name__ == '__main__':
    foo(1, 0)

Также обратите внимание, поскольку вы находитесь в цикле while, когда вы нажимаете Ctrl+C, чтобы остановить цикл, поднимается KeyboardInterrupt, что поднимает ZeroDivisonError из вашего ExceptionCatcher (поскольку __exit__ не вернулся True в конце).

person Dinko Pehar    schedule 29.04.2020