Package: exdec
exdecDecorator for catching exceptions in functions and methods. And also with the possibility of preliminary processing of incoming data, and post-processing of the function result.Works with both synchronous and asynchronous functions and methods;Catches exceptions of the required types;Three types of handlers are available: before the start of the function, after its end, and the exception handler;Handlers can be both synchronous and asynchronous;All current information about the function is available in any handler;Ability to change the incoming data and the result of the function in the handlers;Several ways to fine-tune and pre-configure the decorator;Decorator argumentsnameannotationdefaultAll positional arguments (i.e.*args)Type[Exception]ExceptionexcludeboolFalsebefore_handlerOptional[Callable[[FuncInfo],None]]Noneafter_handlerOptional[Callable[[FuncInfo],None]]Noneexc_handlerCallable[[FuncInfo],Any]exdec.utils.default_exc_handlerextraAnyNonemanagerexdec.manager.ManagerManager()Ifexcludeset toFalse, thenexc_handlerwill handle exceptions from*args.  If set toTrue, thenexc_handlerwill handle all exceptions except those specified in*args.In theextraargument you can specify arbitrary data to be passed to the handlers.All handlers have anFuncInfoargument:# exdec/data_classes.py@dataclassclassFuncInfo:""" Decorated function information.`result` will be available in the handler after calling the function ifno exception occurs.If an exception occurs during the execution of the function, it will bestored in `exception`. This information will be available in the exceptionhandler."""func:Callableargs:Tuple[Any,...]kwargs:Dict[str,Any]result:Any=Noneexception:Optional[Exception]=Noneextra:Any=None...InstallationpipinstallexdecQuick startMore examples in theexamples folder.fromtypingimportOptionalfromexdec.data_classesimportFuncInfofromexdec.decoratorimportcatch# 1 --------------------------------------------------------------------------# Catching all exceptions@catchdefsafe_div_1(x:int,y:int)->Optional[float]:returnx/yassertsafe_div_1(3,3)==1.0assertsafe_div_1(3,0)isNone# 2 --------------------------------------------------------------------------# Catching only ZeroDivisionError@catch(ZeroDivisionError)defsafe_div_2(x:int,y:int)->Optional[float]:returnx/yassertsafe_div_2(3,0)isNone# 3 --------------------------------------------------------------------------HANDLER_RESULT=0.0defexc_handler(func_info:FuncInfo)->float:msg=f"Caught an exception! func_info={func_info}."print(f"{msg}Result changed to{HANDLER_RESULT}")returnHANDLER_RESULT# Catching only ZeroDivisionError@catch(ZeroDivisionError,exc_handler=exc_handler)defsafe_div_3(x:int,y:int)->float:returnx/yassertsafe_div_3(3,0)==HANDLER_RESULT# 4 --------------------------------------------------------------------------classMyException_1(Exception):passclassMyException_2(Exception):pass# Catching all exceptions, except for (MyException_1, MyException_2)@catch(MyException_1,MyException_2,exclude=True,exc_handler=exc_handler)defsafe_div_4(x:int,y:int)->float:returnx/yassertsafe_div_4(3,0)==HANDLER_RESULT# 5 --------------------------------------------------------------------------# For methods everything works the sameclassMathFunctions:# Catching only ZeroDivisionError@catch(ZeroDivisionError)defsafe_div_5(self,x:int,y:int)->Optional[float]:returnx/ymath_functions=MathFunctions()assertmath_functions.safe_div_5(3,0)isNone# 6 --------------------------------------------------------------------------defexc_handler_reraise(func_info:FuncInfo)->float:print(f"Caught an exception! func_info={func_info}.\nRERAISE!")raisefunc_info.exception# Catching only (MyException_1, ZeroDivisionError) and reraise@catch(MyException_1,ZeroDivisionError,exc_handler=exc_handler_reraise)defdiv_6(x:int,y:int)->float:returnx/ydiv_6(3,0)# ZeroDivisionError