Created
February 22, 2019 19:29
-
-
Save ultrafunkamsterdam/db2a0ff6d4ea189b893b9d24374f33e0 to your computer and use it in GitHub Desktop.
Revisions
-
ultrafunkamsterdam created this gist
Feb 22, 2019 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,87 @@ import asyncio import functools import time __all__ = ['Retry'] class Retry(object): """ Python Retry - Automatically retry your calls using optional delay [detects blocking or non-blocking] This wrapper/decorator will retry the wrapped function if: - there is no return value - an exception occured """ def __init__(self, retries=5, delay=2, debug=True, ignore_exc_types=()): """ Will retry the wrapped function if there is no return value or an exception is raised If the decorated function is running inside an asyncio event loop, the delay is non-blocking :param retries (int) : number of retries before giving up :param delay (float) : delay in seconds between each retry attempt :param debug (bool) : print retry attempts to console :param ignore_exc_types (iterable) : iterable of exception classes that not trigger retrying """ self.retries = retries self.delay = delay self._debug = debug self.ignore_exc_types = ignore_exc_types try: self._async = asyncio.get_running_loop() except: self._async = False def __call__(self, fn): if not self._async: @functools.wraps(fn) def decorated(*a, **k): result = None last_exception = None for attempt in range(self.retries): try: result = fn(*a, **k) if result: return result except self.ignore_exc_types as e: last_exception = e if self._debug: print('{} retrying {} - in {} seconds - attempt {}/{}'.format( self.__class__.__name__, fn.__name__, self.delay, attempt + 1, self.retries)) time.sleep(self.delay) if last_exception is not None: raise type(last_exception) from last_exception return result return decorated elif self._async: @functools.wraps(fn) async def decorated(*a, **k): result = None last_exception = None for attempt in range(self.retries): try: result = fn(*a, **k) if result: return result except self.ignore_exc_types as e: last_exception = e if self._debug: print('{} retrying {} - in {} seconds - attempt {}/{}'.format( self.__class__.__name__, fn.__name__, self.delay, attempt + 1, self.retries)) await asyncio.sleep(self.delay) if last_exception is not None: raise type(last_exception) from last_exception return result return decorated