Reputation: 173
Is there a more concise way to perform this in Python:
tries = 10
for x in range(tries):
try:
foo()
break
except Exception as e:
if x == tries-1:
raise e
The point of it is that sometimes the operation fails (for whatever reason), but we want to allow for a number of retries before raising an exception.
Upvotes: 3
Views: 197
Reputation: 40894
A usual way to make something more concise is to factor it out.
def retrying(max_attempts, func, *args, **kwargs):
attempts_left = max_attempts
while attempts_left: # could be 'while True', but an extra check won't hurt
try:
return func(*args, **kwargs)
except SomeException:
attempts_left -= 1
if not attempts_left:
raise
The above code only catches SomeException
and not Exception
, else it would keep retrying when you have an undefined identifier in your code. Usually catching all exceptions is a bad idea, unless you re-raise them immediately. The lone raise
preserves the func
's stack trace. You could pass the list of exceptions to catch as a parameter.
The code above does most sense if you have several places where you need to retry actions. Then you just write retrying(3, foo, 1, b=2)
instead of foo(1, b=2)
.
Upvotes: 4
Reputation: 1265
This is the same as @9000 solution, keeping it's advantages: encapsulated functionality, preserved stack trace. It changes two things: Using a for-loop instead of a while-loop and counting down instead of up.
def retrying(max_attempts, func, *args, **kwargs):
for attempts_left in reversed(range(max_attempts)):
try:
return func(*args, **kwargs)
except ValueError:
if not attempts_left:
raise
For my taste/brain, the for-loop is easier to grasp: a collection is being processed until its end is reached. while-loops always make me search for the catch.
Counting down matches my intuitive understanding better.
A matter of taste, I guess, but for the reasons above I definitely prefer this one.
Upvotes: 0
Reputation: 7369
Essentially the same but slightly more concise...
x = 10
while x > 0:
try:
foo()
break
except Error:
if x == 1: raise Exception('')
x -= 1
Upvotes: 0
Reputation: 23251
Try this:
tries = 10
for _ in range(tries):
try:
foo()
except Exception as e:
pass
else:
break
else:
raise e
Upvotes: 3
Reputation: 1500
Shouldn't this do what you want:
tries = 10
for x in range(tries):
try:
foo()
break
except Exception as e:
pass
The first time foo() succeeds you break out and are done.
Upvotes: -2