Подтвердить что ты не робот

Повторно назначить исключение из блока python __exit__

Изнутри блока __exit__ в пользовательском классе курсора я хочу поймать исключение, поэтому я могу в свою очередь бросить более конкретное исключение. Каков правильный способ сделать это?

class Cursor:
    def __enter__(self):
        ...

    def __exit__(self, ex_type, ex_val, tb):
        if ex_type == VagueThirdPartyError:
            # get new more specific error based on error code in ex_val and
            # return that one in its place.
            return False # ?
        else:
            return False

Поднятие конкретного исключения в блоке __exit__ кажется взломанным, но, возможно, я об этом думаю.

4b9b3361

Ответ 1

Правильная процедура заключается в том, чтобы поднять новое исключение внутри обработчика __exit__.

Вы не должны поднимать исключение, которое было принято; для обеспечения цепочки контекстных менеджеров, в этом случае вам нужно просто вернуть значение false из обработчика. Однако ваши собственные исключения - это прекрасно.

Обратите внимание, что лучше использовать тест идентификации is для проверки типа прошедшего исключения:

def __exit__(self, ex_type, ex_val, tb):
    if ex_type is VagueThirdPartyError:
        if ex_val.args[0] == 'foobar':
            raise SpecificException('Foobarred!')

        # Not raising a new exception, but surpressing the current one:
        if ex_val.args[0] == 'eggs-and-ham':
            # ignore this exception
            return True

        if ex_val.args[0] == 'baz':
            # re-raise this exception
            return False

    # No else required, the function exits and `None` is  returned

Вы также можете использовать issubclass(ex_type, VagueThirdPartyError), чтобы разрешать подклассы конкретного исключения.