Is there a way to implement something like this:
for row in rows:
try:
something
except:
restart iteration
You could put your try/except block in another loop and then break when it succeeds:
for row in rows:
while True:
try:
something
break
except Exception: # Try to catch something more specific
pass
You could make rows an iterator and only advance when there is no error.
it = iter(rows)
row = next(it,"")
while row:
try:
something
row = next(it,"")
except:
continue
On a side note, if you are not already I would catch specific error/errors in the except, you don't want to catch everything.
If you have Falsey values you could use object as the default value:
it = iter(rows)
row, at_end = next(it,""), object()
while row is not at_end:
try:
something
row = next(it, at_end)
except:
continue
Although I wouldn't recommend that, the only way to do this is to make a While (True) Loop until it gets something Done.
Bear in mind the possibility of a infinite loop.
for row in rows:
try:
something
except:
flag = False
while not flag:
try:
something
flag = True
except:
pass
Have your for loop inside an infinite while loop. Check the condition where you want to restart the for loop with a if else condition and break the inner loop. have a if condition inside the while loop which is out side the for loop to break the while loop.
Like this:
while True:
for row in rows:
if(condition)
.....
if(condition)
break
if(condition)
break
Try this
it = iter(rows)
while True:
try:
something
row = next(it)
except StopIteration:
it = iter(rows)
My 2ยข, if rows is a list, you could do
for row in rows:
try:
something
except:
# Let's restart the current iteration
rows.insert(rows.index(row), row)
continue # <-- will skip `something_else`, i.e will restart the loop.
something_else
Also, other things being equal, for-loops are faster than while-loops in Python. That being said, performance is not a first order determinant in Python.
I think user2555451's answer does it pretty well. That being said, you should use continue instead of pass as it will make sure the while True loop is restarted.
for row in rows:
while True:
try:
...
break
except Exception:
continue
I will explain it for newer Python users:
break only breaks the loop you're working in. So if you have something like this: (the variables and functions are imaginary)
for x in imgWidth:
for y in imgHeight:
if ...:
break
drawPixel(x, y, "#FF0000")
and you somehow want to skip a pixel, you can break the loop as it will return to the previous level. The same is true for continue.
Now back to the example:
for row in rows:
while True:
try:
...
break
except Exception:
continue
You move any code you would like to run inside the try block. It will try to do it, and if it catches an error, it will retry because we continue the while True loop! When it finally does the code without errors, it breaks and now it's back in the for loop. Then it continues to the next iteration as it has nothing left to do.
Here is a simple version without using nested loops, an infinite while loop, or mutating the original iterator. Also, it controls the number of attempts with a max_retry parameter:
def do_something(retry=0, max_retry=4):
try:
print('something')
except Exception as e:
if retry == max_retry:
print(f"Max retries reached!")
raise e
do_something(retry=retry + 1)
do_something()
Related
Consider the following
for i in range(100):
if cond1:
cleanup()
continue
if cond2:
cleanup()
continue
if cond3:
cleanup()
continue
...
do_work()
I was wondering if there is a way to write this construct in a more concise way, such that at least there won't be the cleanup(); continue duplicated fragment.
It is almost like I want a goto inside the cleanup to just go back to the top of the loop, or to push the continue into the cleanup function.
Is there a way to do something like that?
EDIT with a more elaborate example:
for i in range(100):
if a == 1:
cleanup()
continue
b = input()
if a + b == 2:
cleanup()
continue
c = input()
if a + b + c:
cleanup()
continue
...
do_work()
You will notice I want each condition to stop or continue iteration, which can't be done with or. Even if it can, this makes reading the code much simpler and linear.
If your conditions are simple, just do one if cond1 or cond2 or cond3: but I'm guessing that the actual code is more complex than that.
Assuming your conditions are complex and/or involved some preparations that require those clean ups, you can enclose them in a one-iteration for-loop that you break when no conditions are met. This will allow you to centralize the cleanup()/continue in an else: statement
for i in range(100):
for preconditions in [1]:
...
if cond1: continue
...
if cond2: continue
...
if cond3: continue
break # final break when no conditions are met
else:
cleanup()
continue
do_work()
Note that you could do something similar with a custom exception and enclosing the conditions in a try/except statement but that seemed a bit overkill so I didn't include it in the answer
No; you can only control the loop from directly in the loop. cleanup cannot assume it will be called from a loop, so indirect breaks and continues are not allowed.
At least for the code shown, you can combine the various if statements into one:
for i in range(100):
if cond1 or cond2 or cond3:
cleanup()
continue
do_work()
Otherwise, you need to examine the return value of cleanup to determine whether to continue the loop or not.
it is possible to not increment count in for loop in case an error happen, like this example
for i in range(10):
try:
print(i)
except: # if and error happen in i == 5 the next iteration will be 5 not 6
pass
I want to repeat the same iteration when the error happen. And thanks in advance.
When you use for...in there's no way to avoid going to the next item in the iteration when the loop repeats.
You can use a nested loop to keep trying with the same value of i until you don't get an error:
for i in range(10):
while True:
try:
print(i)
break
except:
pass
Maybe wrap all into a while loop:
for i in range(10):
while True
try:
# whatever you have to do
print(i)
break
except:
pass
Since Python's for loop is technically a foreach loop you should use a while instead of for for more control.
i = 0
while i<10:
try:
#Do stuf
i += 1
except:
pass
If an error happens before i += 1 it will not be incremented.
This question already has answers here:
Redo for loop iteration in Python
(7 answers)
Closed 3 years ago.
When exception occurs it skips the current "y". I can't manage to prevent this.
for x in range(1, 100):
for y in range(1, 100):
try:
text = requests.post(url, {"x":a, "y":b})
except:
time.sleep(10)
solved with while True but now it doesnt break the first loop
You can wrap the try/except block in a loop and include a break statement at the end of the try block. Your program will continue to try to make the post request until it succeeds and reaches the break. If requests.post encounters an exception, the program will skip the break and move to the except block, wait, then try again.
For example:
for x in range(1, 100):
for y in range(1, 100):
while True:
try:
text = requests.post(url, {"x":a, "y":b})
break
except:
time.sleep(10)
Edit
Since you mentioned that for each x, the program should try each y until finding the correct y, at which point the program should skip to the next x, I've added this update. To do this, you can keep a variable to track if the correct y has been found yet. Then after each y is tried, you can check the value of this variable (found_correct_y) and if it is True, break out of the for y in ... loop and on to the next value of x.
Here's an example:
for x in range(1, 100):
found_correct_y = False
for y in range(1, 100):
while True:
try:
response = requests.post(url, {"x":a, "y":b})
found_correct_y = was_correct_y(response)
break # out of the 'while True' loop
except:
time.sleep(10)
if found_correct_y:
break # out of the 'for y ...' loop, to the next x
def was_correct_y(response):
"""returns a boolean based on some properties of the response"""
pass
I raised an exception in the inner 'y' block and still had success, ie looping back to the 'x' block.
for x in range(1, 10):
for y in range(1, 10):
try:
#text = requests.post(url, {"x":a, "y":b})
print('y',y,'x',x)
if (x==2):
raise
except:
time.sleep(10)
I want to do something like shown below for my project.
whenever any exception will occur I want to start the for loop from current position of 'i'
for eg:
if exception occured at i=3 then my for statement should again start from i=3 till end
Example
for i in range(5):
try:
# some code
except Exception as e:
restart_for_loop_from_current i
Thanks in advance
You could use a nested loop. Something like this would work:
for i in range(5):
loop = True
while loop:
try:
# some code
loop = False
except Exception as e:
# some code make sure this while loop is not endless
pass
Why not change the for-loop to a while-loop? Just increment the variable when no exception occurred, something like this:
while i < 5:
try:
# loop operations
i = i + 1
except:
error = error + 1
# error handling code
my code below tries to execute a function x but because x takes time to build, i need to sleep until it is built then call it. So it usually takes me about 300s to build. When i run the code below, it will loop through the try loop about 3 times but print 0 every time it pass through the except code.
Is it right to put the print x (for when code succeeds and i break) outside the for loop like below or somewhere else? Also, how do i make i print the number of time it is trying instead of 0?
for i in range(0,10):
while True:
try:
x = my_get_fuction
except:
print "error"
print i
time.sleep(100)
continue
break
print x
Your while loop doesn't seem to be related to your design. Try this:
for i in range(0,10):
try:
x = my_get_fuction
except:
print "error"
print i
time.sleep(100)
continue
break
print x
This code will loop a maximum of 10 times, sleeping each time for 100s. If the assigned x = my_get_function doesn't complete by 1000s or so, then the loop gives up.