I'm attempting an operation in Python, and if it fails in certain ways I'd like to retry up to 10 times. If it fails in any other way I'd like it to fail immediately. After 10 retries I'd like all failures to propagate to the caller.
I've been unable to code the flow control in a satisfying way. Here's one example of the behavior (but not the style!) I want:
def run():
max_retries = 10
for retry_index in range(max_retries):
try:
result = run_operation()
except OneTypeOfError:
if retry_index < max_retries - 1:
continue
else:
raise
if result.another_type_of_error:
if retry_index < max_retries - 1:
continue
else:
raise AnotherTypeOfError()
try:
result.do_a_followup_operation()
except AThirdTypeOfError:
if retry_index < max_retries - 1:
continue
else:
raise
return result
raise Exception("We don't expect to end up here")
At first I thought I could just refactor this so the retry logic is separate from the error handling logic. The problem is that if, for example, OneTypeOfError is raised by result.do_a_followup_operation(), I don't want to retry at all in that case. I only want to retry in the specific circumstances coded above.
So I thought perhaps I could refactor this into a function which returns the result, a raised Exception (if any), and a flag indicating whether it's a retryable exception. Somehow that felt less elegant than the above to me.
I'm wondering if there are any flow control patterns in Python which might help here.