how to exit try loop after code succeed? - python

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.

Related

It is possible to not increment count in for loop - Python

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.

Python - break statement not working in else statement within while loop

The while loop in my code refuses to terminate when I use the break statement, and I'm really confused why this is happening.
point = 0
while point < len(list_of_line_lists) - 1:
sentence = list_of_line_lists[point]["text"]
datapoint = point
while True:
try:
if list_of_line_lists[datapoint]["author"] == list_of_line_lists[datapoint + 1]["author"]:
sentence += list_of_line_lists[datapoint + 1]["text"]
datapoint += 1
print(datapoint)
else:
print("this isn't breaking")
break
except IndexError:
break
In my code above, the break statement within the else statement refuses to trigger. The code within it is executed, as there's a flurry of "this isn't breaking" in the output, but the loop itself doesn't terminate. This is how my output looks(until I manually stop it myself):
this isn't breaking
this isn't breaking
this isn't breaking
this isn't breaking
this isn't breaking
this isn't breaking
this isn't breaking
Any ideas to why this is happening?
The inner loop is breaking, but the outer loop isn't. The reason is because you are using the point variable in the outer while loop, but that (point) variable value is never changed (incremented/decremented).

Can you "restart" the current iteration of a Python loop?

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()

breaking out of the loop?

I'm having some trouble with breaking out of these loops:
done = False
while not done:
while True:
print("Hello driver. You are travelling at 100km/h. Please enter the current time:")
starttime = input("")
try:
stime = int(starttime)
break
except ValueError:
print("Please enter a number!")
x = len(starttime)
while True:
if x < 4:
print("Your input time is smaller than 4-digits. Please enter a proper time.")
break
if x > 4:
print("Your input time is greater than 4-digits. Please enter a proper time.")
break
else:
break
It recognizes whether the number is < 4 or > 4 but even when the number inputted is 4-digits long it returns to the start of the program rather than continues to the next segment of code, which isn't here.
You obviously want to use the variable done as a flag. So you have to set it just before your last break (when you are done).
...
else:
done = 1
break
The reason it "returns to the beginning of the program" is because you've nested while loops inside a while loop. The break statement is very simple: it ends the (for or while) loop the program is currently executing. This has no bearing on anything outside the scope of that specific loop. Calling break inside your nested loop will inevitably end up at the same point.
If what you want is to end all execution within any particular block of code, regardless of how deeply you're nested (and what you're encountering is a symptom of the issues with deeply-nested code), you should move that code into a separate function. At that point you can use return to end the entire method.
Here's an example:
def breakNestedWhile():
while (True):
while (True):
print("This only prints once.")
return
All of this is secondary to the fact that there's no real reason for you to be doing things the way you are above - it's almost never a good idea to nest while loops, you have two while loops with the same condition, which seems pointless, and you've got a boolean flag, done, which you never bother to use. If you'd actually set done to True in your nested whiles, the parent while loop won't execute after you break.
input() can take an optional prompt string. I've tried to clean up the flow a bit here, I hope it's helpful as a reference.
x = 0
print("Hello driver. You are travelling at 100km/h.")
while x != 4:
starttime = input("Please enter the current time: ")
try:
stime = int(starttime)
x = len(starttime)
if x != 4:
print("You input ({}) digits, 4-digits are required. Please enter a proper time.".format(x))
except ValueError:
print("Please enter a number!")

Can't get a function to work

I am try to create a function that will end my game with a message counting down until it ends, and I am having to repeat this block of code a lot in my text adventure game, so I decided to make a function of it for the sake of neatness, and efficiency. But I cannot figure out how to define and call such a function. This is the code I am trying to execute:
print "That\'s a real shame..."
time.sleep(1)
print 'Exiting program in 5 seconds:'
time.sleep(1)
print '5'
time.sleep(1)
print '4'
time.sleep(1)
print '3'
time.sleep(1)
print '2'
time.sleep(1)
print '1'
time.sleep(1)
sys.exit('Exiting Game...')
break
So I defining the function like this:
def exit():
print "That\'s a real shame..."
time.sleep(1)
print 'Exiting program in 5 seconds:'
time.sleep(1)
print '5'
time.sleep(1)
print '4'
time.sleep(1)
print '3'
time.sleep(1)
print '2'
time.sleep(1)
print '1'
time.sleep(1)
sys.exit('Exiting Game...')
break
And I am calling the function like this:
elif ready == 'n':
exit
What am I doing wrong?
You would call the function by typing exit(). I modified your countdown code and turned it into a function that I called inside exit() to demonstrate how to call one function from piece of code.
def exit():
print "That\'s a real shame..."
time.sleep(1)
print 'Exiting program in 5 seconds:'
time.sleep(1)
count_down(5) # Call Countdown clock
print 'Exiting Game...'
sys.exit()
def count_down(number):
for i in reversed(range(number)):
print i+1
time.sleep(1)
exit() # <-- This how you call exit, you were missing the parentheses at the end.
Output:
That's a real shame...
Exiting program in 5 seconds:
5
4
3
2
1
Exiting Game...
Edit: Added more in-depth explanation.
The first linedef count_down is a function that takes one parameter and has one purpose, to handle the count down.
def count_down(number):
The second row contains what we call a for loop. The purpose of this code is to loop through objects. Starting from 4 then 3,2,1 etc. And the variable i at the same row will change for each time the loop goes through a number and is accessible only inside the loop. The first time print is executed it will be 5, then the next time 4 and so on.
for i in reversed(range(number)):
In this function we also use two additional keywords and one parameter, reversed, range and the parameter number.
reversed(range(number))
range is used to create a list of numbers e.g. [0, 1, 2, 3, 4], that the for statement will loop through starting with 0, then it takes the next number all the way until it reaches the last number 4. I will explain why it starts at zero and only goes to four, and not five at the end of my answer.
reversed is used to reverse the list we created with range. Since we want to start at 4, and not 0.
Before reversed => [0,1,2,3,4]
After reversed] => [4,3,2,1,0]
number is a parameter. A parameter is a value that we provide when we execute the function from your exit() function by including a value inside the parentheses (). In this case we specified 5, so the list we created with
range will range from 0 - 4 (0,1,2,3,4 = five numbers in total). If you instead specified 10 within the parentheses it would create a list starting from 0 all the way to 9. And your code would count down from 10 to 1, instead of from 5 to 1.
When Python has started working on the for loop it will execute the code inside, starting with print and then sleep, and continues to do so for for each number in the list created by range. Since we specified five in this case, it will execute the code a total of five times.
As Python is executing the code within the for loop it will first call the print function. Because the for loop will start at 4, not 5, we need to do some basic arithmetics and increase the value of each item we loop through by one. We do this by typing + 1 after our variable i.
The reason why it starts at 4 and not 5 is because in programming lists starts with the number 0, and not 1. There is a more technical explanation available on the reason why lists start with 0, and not 1 (or 4, and not 5 in this case since we reversed the list) here
You are supposed to call it as exit(), not exit.
It is simple. Use a tuple that holds the message and the timer delay so you can even control the delay time for each message.
import time, sys
messages = [
("That's a shame", 1),
("Exiting program in 5 seconds", 1),
(None, 5)
]
for k,v in messages:
if k:
print(k)
time.sleep(v)
else:
# start countdown timer
while v:
print v
time.sleep(1)
v -= 1
sys.exit()
A good way to do this code is:
def exit():
timer= 5
print "That\'s a real shame..."
time.sleep(1)
print 'Exiting program in 5 seconds:'
for i in range (5):
time.sleep(1)
print timer
timer = timer - 1
sys.exit('Exiting Game...')
##You call the function like this
exit()

Categories