Reputation: 1
suppose I have an exception that is (unpredictably/inconsistently) raised at different lines in the script every time I run it. How can I handle this exception in such a way that (1) forces the script to sleep for a few seconds following the error then (2) tries to re-execute the same line of code that caused the error in hopes of a successful result the 2nd time around (or 3rd, or 4th ...), AND (3) does not re-execute all of the lines leading up to that point in the script? In other words, I want it to "goto" the previous line and try again until it succeeds, albeit with a cap on the number of attempts to avoid an infinite loop.
The code below is conceptual example of my problem. The desired result would print:
A B C D E
but instead prints something like:
A A B A B A A A A B A A A B C D E
import time, random
success, attempts = False, 0
while success == False and attempts <= 20:
try:
x, y = 1, random.choice([0,1])
x/y
print "A"
x, y = 1, random.choice([0,1])
x/y
print "B"
x, y = 1, random.choice([0,1])
x/y
print "C"
x, y = 1, random.choice([0,1])
x/y
print "D"
x, y = 1, random.choice([0,1])
x/y
print "E"
success = True
except ZeroDivisionError:
attempts += 1
time.sleep(3)
Thanks in advance.
Upvotes: 0
Views: 372
Reputation: 532023
You can use conditionals and an explicitly tracked to-do list to fake a set of goto's. Each time a task succeeds, remove it from the to-do list so that you won't try it again.
import time, random
attempts = 0
# Reverse order because it's more efficient to remove an item
# from the end of a list than the beginning. Use a deque
# if this bothers you.
to_do = ["E", "D", "C", "B", "A"]
while to_do and attempts <= 20:
try:
if to_do[-1] == "A":
x, y = 1, random.choice([0,1])
x/y
print "A"
to_do.pop()
elif to_do[-1] == "B":
x, y = 1, random.choice([0,1])
x/y
print "B"
to_do.pop()
elif to_do[-1] == "C":
x, y = 1, random.choice([0,1])
x/y
print "C"
to_do.pop()
elif to_do[-1] == "D":
x, y = 1, random.choice([0,1])
x/y
print "D"
to_do.pop()
elif to_do[-1] == "E":
x, y = 1, random.choice([0,1])
x/y
print "E"
to_do.pop()
except ZeroDivisionError:
attempts += 1
time.sleep(3)
However, this can be cleaned up significantly by defining a separate function for each task, and using the presence of the function itself
on your failures
list to indicate it still needs to be run.
to_do = [task_e, task_d, task_c, task_b, task_a]
while attempts <= 20:
while to_do:
try:
to_do[-1]()
except ZeroDivisionError:
attempts += 1
time.sleep(3)
else:
to_do.pop()
Upvotes: 1