Last active
July 19, 2017 22:51
-
-
Save JesterEE/05d218c0ecc040162853251ac0a9703e to your computer and use it in GitHub Desktop.
Example using the retrying module with a generator.See docstrings for details.
This file contains 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 characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
from retrying import retry | |
import datetime | |
import time | |
class RetryingTimeWrappedGeneratorClass: | |
"""Class to illustrate how to use `retrying` with a generator. | |
The `@retry` decorator must be placed on the function execution "inside" | |
the iteration of the generator. If an error is caught, the iterator will | |
not progress, and the retried function will operate on the same value of | |
the generator as determined by the `@retry` decorator. | |
Note that a class was needed here to carry state information for | |
`self.time_target` between iterations. If state is not necessary for a | |
specific generator/iterator use case, 3 separate functions | |
(generator, iterator, and "main") can be used outside of a class.""" | |
def __init__(self, rng, wait, delta_sec): | |
self.rng = rng | |
self.wait = wait | |
self.delta_sec = delta_sec | |
self.time_target = datetime.datetime.now() + datetime.timedelta(seconds=delta_sec) | |
@staticmethod | |
def calc_square_generator(rng): | |
"""Generator for squared numbers.""" | |
mylist = range(rng) | |
for n in mylist: | |
yield n * n | |
def calc_square_generator_loop(self): | |
"""Iterator for the square number generator.""" | |
print("TARGET: {}".format(self.time_target)) | |
for v in self.calc_square_generator(self.rng): | |
self.calc_square_generator_loop_wrapped(v) | |
@retry(retry_on_exception=lambda e: isinstance(e, ValueError), wait_random_min=1000, wait_random_max=2000, | |
stop_max_attempt_number=2, wrap_exception=True) | |
def calc_square_generator_loop_wrapped(self, v): | |
""""Main" function to do something over the iteration of the generator. | |
Here, the value of the generator is not used ... we just check the time | |
to determine if we ran for too long. | |
Note: Each iteration of this function is a separate call ... so setting | |
a maximum delay time is not helpful (for this simple function). | |
However, to illustrate how the decorator arguments might be | |
helpful, a random min/max wait time is set in conjunction with a | |
maximum number of attempts. If | |
`wait_random_max` ~>= `self.delta_sec`, there is a possibility | |
that this function can fail multiple times consecutively, causing | |
the failure condition | |
(`stop_max_attempt_number` consecutive `ValueError`s). | |
""" | |
print('NOW: {} {}'.format(v, datetime.datetime.now())) | |
if datetime.datetime.now() > self.time_target: | |
self.time_target = self.time_target + datetime.timedelta(seconds=self.delta_sec) | |
print('Took too long ... time_target: Added {} seconds to execution.'.format(self.delta_sec)) | |
raise ValueError('Poof ... time flew by!') | |
time.sleep(self.wait) | |
if __name__ == '__main__': | |
wrapped_generator = RetryingTimeWrappedGeneratorClass(rng=10, wait=1, delta_sec=2) | |
wrapped_generator.calc_square_generator_loop() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment