Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to show traceback after each failed retry #44

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ retry decorator
:param backoff: multiplier applied to delay between attempts. default: 1 (no backoff).
:param jitter: extra seconds added to delay between attempts. default: 0.
fixed if a number, random if a range tuple (min, max)
:param show_traceback: Print traceback before retrying (Python3 only). default: False.
:param logger: logger.warning(fmt, error, delay) will be called on failed attempts.
default: retry.logging_logger. if None, logging is disabled.
"""
Expand Down Expand Up @@ -122,6 +123,7 @@ retry_call
:param backoff: multiplier applied to delay between attempts. default: 1 (no backoff).
:param jitter: extra seconds added to delay between attempts. default: 0.
fixed if a number, random if a range tuple (min, max)
:param show_traceback: Print traceback before retrying (Python3 only). default: False.
:param logger: logger.warning(fmt, error, delay) will be called on failed attempts.
default: retry.logging_logger. if None, logging is disabled.
:returns: the result of the f function.
Expand Down
19 changes: 12 additions & 7 deletions retry/api.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import logging
import random
import sys
import time

import traceback
from functools import partial

from .compat import decorator


logging_logger = logging.getLogger(__name__)


def __retry_internal(f, exceptions=Exception, tries=-1, delay=0, max_delay=None, backoff=1, jitter=0,
logger=logging_logger):
show_traceback=False, logger=logging_logger):
"""
Executes a function and retries it if it failed.

Expand All @@ -36,7 +36,12 @@ def __retry_internal(f, exceptions=Exception, tries=-1, delay=0, max_delay=None,
if not _tries:
raise

assert not show_traceback or logger is not None, 'Show traceback needs logger'
assert not show_traceback or sys.version_info[0] != 2, 'Traceback not supported in Python2'
if logger is not None:
if show_traceback:
tb_str = ''.join(traceback.format_exception(None, e, e.__traceback__))
logger.warning(tb_str)
logger.warning('%s, retrying in %s seconds...', e, _delay)

time.sleep(_delay)
Expand All @@ -51,7 +56,7 @@ def __retry_internal(f, exceptions=Exception, tries=-1, delay=0, max_delay=None,
_delay = min(_delay, max_delay)


def retry(exceptions=Exception, tries=-1, delay=0, max_delay=None, backoff=1, jitter=0, logger=logging_logger):
def retry(exceptions=Exception, tries=-1, delay=0, max_delay=None, backoff=1, jitter=0, show_traceback=False, logger=logging_logger):
"""Returns a retry decorator.

:param exceptions: an exception or a tuple of exceptions to catch. default: Exception.
Expand All @@ -71,13 +76,13 @@ def retry_decorator(f, *fargs, **fkwargs):
args = fargs if fargs else list()
kwargs = fkwargs if fkwargs else dict()
return __retry_internal(partial(f, *args, **kwargs), exceptions, tries, delay, max_delay, backoff, jitter,
logger)
show_traceback, logger)

return retry_decorator


def retry_call(f, fargs=None, fkwargs=None, exceptions=Exception, tries=-1, delay=0, max_delay=None, backoff=1,
jitter=0,
jitter=0, show_traceback=False,
logger=logging_logger):
"""
Calls a function and re-executes it if it failed.
Expand All @@ -98,4 +103,4 @@ def retry_call(f, fargs=None, fkwargs=None, exceptions=Exception, tries=-1, dela
"""
args = fargs if fargs else list()
kwargs = fkwargs if fkwargs else dict()
return __retry_internal(partial(f, *args, **kwargs), exceptions, tries, delay, max_delay, backoff, jitter, logger)
return __retry_internal(partial(f, *args, **kwargs), exceptions, tries, delay, max_delay, backoff, jitter, show_traceback, logger)