Я также обнаружил, что во многих случаях мне нужно немного «обернуть» ошибки.
Это включается как в область действия функции, так и иногда включает только некоторые строки внутри функции.
Создана оболочка для использования decorator
и context manager
:
Осуществление
import inspect
from contextlib import contextmanager, ContextDecorator
import functools
class wrap_exceptions(ContextDecorator):
def __init__(self, wrapper_exc, *wrapped_exc):
self.wrapper_exc = wrapper_exc
self.wrapped_exc = wrapped_exc
def __enter__(self):
pass
def __exit__(self, exc_type, exc_val, exc_tb):
if not exc_type:
return
try:
raise exc_val
except self.wrapped_exc:
raise self.wrapper_exc from exc_val
def __gen_wrapper(self, f, *args, **kwargs):
with self:
for res in f(*args, **kwargs):
yield res
def __call__(self, f):
@functools.wraps(f)
def wrapper(*args, **kw):
with self:
if inspect.isgeneratorfunction(f):
return self.__gen_wrapper(f, *args, **kw)
else:
return f(*args, **kw)
return wrapper
Примеры использования
декоратор
@wrap_exceptions(MyError, IndexError)
def do():
pass
при вызове do
метода, не беспокойтесь о IndexError
, просто MyError
try:
do()
except MyError as my_err:
pass # handle error
менеджер контекста
def do2():
print('do2')
with wrap_exceptions(MyError, IndexError):
do()
внутри do2
, в context manager
, если IndexError
поднят, он будет
быть завернутым и поднятым MyError