Using exception handling inside a loop in python, I'm receiving inputs from a user and adds it to a list but if the user types 'done' the loop terminates and sums up the list. If the user types any other non numeric data it would print 'Wrong Data' and continue the loop. My issues are: Adding the list. Converting the user data from number to string. Reading a string data first from the user. And terminating the loop with 'done'.
total = 0
user_list = []
while True:
try:
user_entry = int(input('(\'done\' is your terminator.)\nEnter any number only! >> '))
user_list.append(user_entry)
total = total + user_list
except ValueError:
if str(user_entry) == 'done':
break
else:
print('Wrong Data')
continue
There's lots of code in the try block that should go before or after the try statement.
total = 0
user_list = []
while True:
user_entry = input('(\'done\' is your terminator.)\nEnter any number only! >> ')
if user_entry == 'done':
break
try:
user_entry = int(user_entry)
except ValueError:
print('Wrong Data')
continue
user_list.append(user_entry)
total += user_entry
Note that instead of keeping running total, you can simply wait until after the loop to call total = sum(user_list).
how repeat code again again again this every work
I want the code below to always work and it should be repeated, and again this function should be repeated and not removed from the program.
def ref(self):
driver = self.driver
nextB2 = driver.find_element_by_xpath("""//section/span/button/span[#aria-label='Like']""")
nextB2.click()
time.sleep(5)
nextB3 = driver.find_element_by_xpath("""//section/span/button/span[#aria-label='Like']""")
nextB3.click()
time.sleep(6)
nextB4 = driver.find_element_by_xpath("""//section/span/button/span[#aria-label='Like']""")
nextB4.click()
time.sleep(7)
driver.refresh()
time.sleep(5)
driver.switch_to_frame('ref')
driver.refresh('ref')
you can use for loop with range to stop at perticular count like
for i in range(10): #10 times
ref() #function call
if you want it to run for ever
while True: #loop that never stops
ref()
you can use break and continue for conditional breaks
while True:
if foo == foo:
break #break or stop the while oop
elif foo == bar:
continue #skip current iteration and continue execution
else:
ref()
I need to emulate a do-while loop in a Python program. Unfortunately, the following straightforward code does not work:
list_of_ints = [ 1, 2, 3 ]
iterator = list_of_ints.__iter__()
element = None
while True:
if element:
print element
try:
element = iterator.next()
except StopIteration:
break
print "done"
Instead of "1,2,3,done", it prints the following output:
[stdout:]1
[stdout:]2
[stdout:]3
None['Traceback (most recent call last):
', ' File "test_python.py", line 8, in <module>
s = i.next()
', 'StopIteration
']
What can I do in order to catch the 'stop iteration' exception and break a while
loop properly?
An example of why such a thing may be needed is shown below as pseudocode.
State machine:
s = ""
while True :
if state is STATE_CODE :
if "//" in s :
tokens.add( TOKEN_COMMENT, s.split( "//" )[1] )
state = STATE_COMMENT
else :
tokens.add( TOKEN_CODE, s )
if state is STATE_COMMENT :
if "//" in s :
tokens.append( TOKEN_COMMENT, s.split( "//" )[1] )
else
state = STATE_CODE
# Re-evaluate same line
continue
try :
s = i.next()
except StopIteration :
break
I am not sure what you are trying to do. You can implement a do-while loop like this:
while True:
stuff()
if fail_condition:
break
Or:
stuff()
while not fail_condition:
stuff()
What are you doing trying to use a do while loop to print the stuff in the list? Why not just use:
for i in l:
print i
print "done"
Update:
So do you have a list of lines? And you want to keep iterating through it? How about:
for s in l:
while True:
stuff()
# use a "break" instead of s = i.next()
Does that seem like something close to what you would want? With your code example, it would be:
for s in some_list:
while True:
if state is STATE_CODE:
if "//" in s:
tokens.add( TOKEN_COMMENT, s.split( "//" )[1] )
state = STATE_COMMENT
else :
tokens.add( TOKEN_CODE, s )
if state is STATE_COMMENT:
if "//" in s:
tokens.append( TOKEN_COMMENT, s.split( "//" )[1] )
break # get next s
else:
state = STATE_CODE
# re-evaluate same line
# continues automatically
Here's a very simple way to emulate a do-while loop:
condition = True
while condition:
# loop body here
condition = test_loop_condition()
# end of loop
The key features of a do-while loop are that the loop body always executes at least once, and that the condition is evaluated at the bottom of the loop body. The control structure show here accomplishes both of these with no need for exceptions or break statements. It does introduce one extra Boolean variable.
My code below might be a useful implementation, highlighting the main difference between do-while vs while as I understand it.
So in this one case, you always go through the loop at least once.
first_pass = True
while first_pass or condition:
first_pass = False
do_stuff()
do {
stuff()
} while (condition())
->
while True:
stuff()
if not condition():
break
You can do a function:
def do_while(stuff, condition):
while condition(stuff()):
pass
But
1) It's ugly.
2) Condition should be a function with one parameter, supposed to be filled by stuff (it's the only reason not to use the classic while loop.)
Exception will break the loop, so you might as well handle it outside the loop.
try:
while True:
if s:
print s
s = i.next()
except StopIteration:
pass
I guess that the problem with your code is that behaviour of break inside except is not defined. Generally break goes only one level up, so e.g. break inside try goes directly to finally (if it exists) an out of the try, but not out of the loop.
Related PEP: http://www.python.org/dev/peps/pep-3136
Related question: Breaking out of nested loops
Here is a crazier solution of a different pattern -- using coroutines. The code is still very similar, but with one important difference; there are no exit conditions at all! The coroutine (chain of coroutines really) just stops when you stop feeding it with data.
def coroutine(func):
"""Coroutine decorator
Coroutines must be started, advanced to their first "yield" point,
and this decorator does this automatically.
"""
def startcr(*ar, **kw):
cr = func(*ar, **kw)
cr.next()
return cr
return startcr
#coroutine
def collector(storage):
"""Act as "sink" and collect all sent in #storage"""
while True:
storage.append((yield))
#coroutine
def state_machine(sink):
""" .send() new parts to be tokenized by the state machine,
tokens are passed on to #sink
"""
s = ""
state = STATE_CODE
while True:
if state is STATE_CODE :
if "//" in s :
sink.send((TOKEN_COMMENT, s.split( "//" )[1] ))
state = STATE_COMMENT
else :
sink.send(( TOKEN_CODE, s ))
if state is STATE_COMMENT :
if "//" in s :
sink.send(( TOKEN_COMMENT, s.split( "//" )[1] ))
else
state = STATE_CODE
# re-evaluate same line
continue
s = (yield)
tokens = []
sm = state_machine(collector(tokens))
for piece in i:
sm.send(piece)
The code above collects all tokens as tuples in tokens and I assume there is no difference between .append() and .add() in the original code.
The way I've done this is as follows...
condition = True
while condition:
do_stuff()
condition = (<something that evaluates to True or False>)
This seems to me to be the simplistic solution, I'm surprised I haven't seen it here already. This can obviously also be inverted to
while not condition:
etc.
I believe that this do-while simulation on python has a syntax format closest to the do-while structure format present in C and Java.
do = True
while do:
[...]
do = <condition>
Python 3.8 has the answer.
It's called assignment expressions. from the documentation:
# Loop over fixed length blocks
while (block := f.read(256)) != '':
process(block)
for a do - while loop containing try statements
loop = True
while loop:
generic_stuff()
try:
questionable_stuff()
# to break from successful completion
# loop = False
except:
optional_stuff()
# to break from unsuccessful completion -
# the case referenced in the OP's question
loop = False
finally:
more_generic_stuff()
alternatively, when there's no need for the 'finally' clause
while True:
generic_stuff()
try:
questionable_stuff()
# to break from successful completion
# break
except:
optional_stuff()
# to break from unsuccessful completion -
# the case referenced in the OP's question
break
While loop:
while condition:
print("hello")
Do while loop:
while True:
print("hello")
if not condition:
break
Also you can use any true boolean value as condition:
while 1:
print("hello")
if not condition:
break
Another variant:
check = 1
while check:
print("hello")
check = condition
Quick hack:
def dowhile(func = None, condition = None):
if not func or not condition:
return
else:
func()
while condition():
func()
Use like so:
>>> x = 10
>>> def f():
... global x
... x = x - 1
>>> def c():
global x
return x > 0
>>> dowhile(f, c)
>>> print x
0
while condition is True:
stuff()
else:
stuff()
Why don't you just do
for s in l :
print s
print "done"
?
If you're in a scenario where you are looping while a resource is unavaliable or something similar that throws an exception, you could use something like
import time
while True:
try:
f = open('some/path', 'r')
except IOError:
print('File could not be read. Retrying in 5 seconds')
time.sleep(5)
else:
break
You wondered:
What can I do in order to catch the 'stop iteration' exception and break a while loop properly?
You could do it as shown below and which also makes use of the assignment expressions feature (aka “the walrus operator”) that was introduced in Python 3.8:
list_of_ints = [1, 2, 3]
iterator = iter(list_of_ints)
try:
while (element := next(iterator)):
print(element)
except StopIteration:
print("done")
Another possibility (that would work from Python 2.6 to 3.x) would be to provide a default argument to the built-in next() function to avoid the StopIteration exception:
SENTINEL = object() # Unique object.
list_of_ints = [1, 2, 3]
iterator = iter(list_of_ints)
while True:
element = next(iterator, SENTINEL)
if element is SENTINEL:
break
print(element)
print("done")
See if this helps :
Set a flag inside the exception handler and check it before working on the s.
flagBreak = false;
while True :
if flagBreak : break
if s :
print s
try :
s = i.next()
except StopIteration :
flagBreak = true
print "done"
For me a typical while loop will be something like this:
xBool = True
# A counter to force a condition (eg. yCount = some integer value)
while xBool:
# set up the condition (eg. if yCount > 0):
(Do something)
yCount = yCount - 1
else:
# (condition is not met, set xBool False)
xBool = False
I could include a for..loop within the while loop as well, if situation so warrants, for looping through another set of condition.
while True:
try:
# stuff
stuff_1()
if some_cond:
continue
if other_cond:
break
stuff_2()
finally:
# condition
if not condition:
break
[x] condition checked only after running stuff
[x] stuff is not a function call
[x] condition is not a function call
[x] stuff can contain flow control
[ ] Avoid checking condition if stuff called break (can be done with another boolean)
The built-in iter function does specifically that:
for x in iter(YOUR_FN, TERM_VAL):
...
E.g. (tested in Py2 and 3):
class Easy:
X = 0
#classmethod
def com(cls):
cls.X += 1
return cls.X
for x in iter(Easy.com, 10):
print(">>>", x)
If you want to give a condition to terminate instead of a value, you always can set an equality, and require that equality to be True.
I'm looking for a way to return to a while loop after it is done.
Basically, in my main code, at the beginning, there is a while loop that I want to do for x amount of times and then exit out and execute some other code. If certain values are met, return to the while loop at the top of the main.
Here is the code that I wrote but once the while loop is finished it just stops.
t = 0
def main():
global t
try:
while t < 3:
distance = Tank_Measurement()
if distance > 5 and distance < 100:
print ('Distance:',distance ,'cm')
Pumping_to_Growbed()
time.sleep(2)
draining_Selenoid()
t = t + 1
else:
print ('Distance:',distance ,'cm is out of range')
time.sleep(1)
Tank_Measurement()
t = t + 1
return
distance = Tank_Measurement()
distance2 = growbed_Measurement()
if distance < 5 and distance2 < 5:
print ('Water level in main tank low')
print ('Filling up main tank')
time.sleep(1)
Pumping_to_mainTank()
t = 0
else:
t = 0
except KeyboardInterrupt:
print ('Exiting program gracefully')
for i in range(3,0,-1):
time.sleep(1)
sys.stdout.write(str(i)+' ')
sys.stdout.flush()
finally:
GPIO.cleanup()
main()
Put the entire body of main() inside another another while loop:
def main():
keep_looping = True
while keep_looping:
... original code here
if some_condition:
keep_looping = False
once the while loop is finished it just stops
That is because you have a return as the next statement after while. So it returns to the point where you called main(), which then is the last line of your code, no further statements or code after that.
Is there a command such as break and continue which could repeat recent iteration?
For example, when exception is thrown.
for i in range(0,500):
try:
conn = getConnection(url+str(i))
doSomething(conn)
except:
repeat
Let's have an iteration where i variable's value is 6. During this iteration some connection error occurred. I want to repeat this iteration.
Is there a command which can do that?
Of course I can do this:
i=0
while i!=500:
try:
conn = getConnection(url+str(i))
doSomething(conn)
i+=1
except:
pass
No, there is no command to "rewind" a for-loop in Python.
You could use a while True: loop inside the for-loop:
for i in range(500):
while True:
try:
conn = getConnection(url+str(i))
doSomething(conn)
except Exception: # Replace Exception with something more specific.
continue
else:
break
or without the else::
for i in range(500):
while True:
try:
conn = getConnection(url+str(i))
doSomething(conn)
break
except Exception: # Replace Exception with something more specific.
continue
But I personally think that your proposed solution is better because it avoids an indentation level.
for i in range(500):
while True
try:
conn = getConnection(url+str(i))
break
except Exception: # still allows to quit with KeyboardInterrupt
continue
do_your_stuff()
This looks bit risky, however, you should at least enable some logging inside a while block.
If you expect to use it in more places, you might write a simple decorator:
def keep_trying(fn, *args, **kwargs):
def inner(*args, **kwargs):
while True:
try:
return fn(*args, **kwargs)
except Exception:
continue
return inner
# later you can use it simple like this:
for i in range(500):
conn = keep_trying(getConnection)(url+str(i))
You can use generators :
def process_connections(n_connections, url, max_tries=50):
i = 0
try_count = 0
while i < n_connections:
try:
conn = getConnection(url+str(i))
yield conn
except:
try_count += 1
if try_count > max_tries:
raise Exception("Unable to connect after %s tries" % max_tries)
else:
i += 1 # increments only if no exception
And you perform your operations :
for conn in process_connections(500, url):
do_something(conn)
You can use nested for loops to put a cap on the number of times you retry the operation. This is bascially the sam as #PierreAlex's generator answer but without the extra function definition.
for i in range(500):
for retry in range(10):
try:
conn = getConnection(url+str(i))
doSomething(conn)
except Exception: # Replace Exception with something more specific.
time.sleep(1)
else:
print "iteration", i, "failed"
Why not just use an if statement?
n=6
i=0
while i!=500:
failed = False;
try:
conn = getConnection(url+str(i))
doSomething(conn)
i+=1
except:
#handle error
failed = True;
#try again if n-th case failed first time
if(i == n and failed):
try:
conn = getConnection(url+str(i))
doSomething(conn)
except:
#handle error
Here is one. You would need to add a logging or alert system to let you know that something is stuck:
state = "" #state of the loop
# If there is no error continue. If there is error, remain in loop
while True:
if state != "error":
try:
1/0 # command
break # no error so break out of loop
except:
state = "error" #declare error so maintain loop
continue
elif state == "error": # maintain loop
continue