Python multiple nested while True continue/end looping error [duplicate] - python

This question already has answers here:
How can I break out of multiple loops?
(39 answers)
Closed 5 years ago.
Here's a piece of code from my project software:
def fun_1(self, i):
print("")
print("Welcome to Option 1: View Passwords")
while True:
print("")
which_o1 = input("1: Input a New Account details \n2: Exit \nPlease Input the option number: ")
if which_o1 == str(1):
with open(str(i)+'.txt', 'a+') as file:
while True:
print("")
web_n = input("Please Input Website name: ")
print("")
e_u = input("Please input email/username: ")
print("")
pass_w = input("Please input password: ")
while True:
print("")
sure = input("Website- " +web_n+"\nEmail/Username- "+e_u+"\nPassword- "+pass_w+"\nAre You sure about these details? Yes/No: ")
if (sure.lower()[0]) != 'y' and (sure.lower()[0]) != 'n':
print("")
print("Please input a valid response Yes/No!")
continue
elif (sure.lower()[0]) == 'y' and (sure.lower()[0]) != 'n':
list_log = [web_n, e_u, pass_w]
file.write(str(list_log) + '\n')
break
break
continue
elif (sure.lower()[0]) == 'n' and (sure.lower()[0]) != 'y':
break
continue
elif which_o1 == str(2):
return (i)
else:
print("")
print("Please Enter a Valid Response!")
continue
So has you can see that it has 3 while True loop. The problem is occurring while breaking and looping the loop. If you see the latest While True under "pass_w" in the middle elif, where it says elif (sure.lower()[0]) == 'y' and (sure.lower()[0]) != 'n':, in it I have 2 break and 1 continue because what I wanted to do is that when that elif executes it just break middle 3rd while true, 2nd while true and continue means loop the first while true at the start of the code, but it just keep looping 3rd While True in the middle of the code instead of breaking it.
Is there a way I can make it possible?

Firstly, understand that no lines can be executed after a break statement inside of a while loop. So putting multiple breaks and a continue won't work. You need to restructure your code. Personally, I would recommend either implementing try except statements, or putting some of the code inside of functions so that you can return when you want to stop looping and pass variables as indications to the outer loops where the function was called.
Another option could be instead of using breaks and continues, use a variable or set of variables that your while loops check for to decide if they should continue. So inside your ifs and elifs you could set exitfirstloop = True, etc. and in the while loops you check while not exitfirstloop

Related

Issue when trying to add user validation [duplicate]

This question already has answers here:
not equals operator(!=) not working in python string comparison
(2 answers)
Closed 1 year ago.
Trying to add validation to user input.
So the code is:
print ('Does this service require an SFP Module? (y/n): ')
while True:
sfpreq = input()
if sfpreq != 'y' or 'n':
print("You must enter either y or n")
continue
else:
break
So even when the user enters 'n' it returns the "print("You must enter either y or n")" and continues the loop.
I have tried setting the variabl manually to and also tried another convention I found on realpython and also removed the if statement from the while loop:
sfpreq = "n"
if sfpreq != 'y' or sfpreq != 'n':
print("You must enter either y or n")
else:
print("Test")
Again it just returns:
admin#MacBook-Pro Learning Folder % python3 test22.py
You must enter either y or n
Am I just missing something very fundamental here?
Problem with the logic
sfpreq = "n"
if sfpreq != 'y' or sfpreq != 'n':
print("You must enter either y or n")
else:
print("Test")
Here, when you enter the if loop,
sfpreq != 'y' is validated as True and sfpreq != 'n' is validated as False.
Now True OR False statement in boolean algebra equates to True.
So, the if loop gets executed and You must enter either y or n is printed.
See, more about boolean algebra here
A better solution
sfpreq = "n"
if sfpreq not in {"y","n"}:
print("You must enter either y or n")
else:
print("Test")
So, here we are checking if y or n is not there in the set {"y","n"}. As in this case, sfpreq is there in that set so,the else statement gets executed.

(Python) Trouble making the user input promt another quiz question or break the loop

I'm pretty new to programming, so please pardon me!
***EDIT 2: Ok so this is the full thing. Everything is working fine except when I try to break out of the while enthusiasm is True: loop, I just keep getting more and more questions (the loop keeps running)
I'm building a Python trivia quiz, and I managed all the answer input loop to work (doesn't allow invalid input, breaks the loop succesfully)
I want the program to ask the user "Would you like another question? (y/n)" and stop the program if 'n'.
The problem is no matter what I tried, I keep getting more trivia questions!
Thanks in advance
import requests
import pprint
import json
import html
print("Welcome to the ultimate test of knowledge and valour, The Internet Quiz!")
print("You will be given an array of multiple choice questions in general knowledge")
input("Press Enter to start!")
y_n = ["y", "n"]
import random
q_num = 1
score = 0
enthusiasm = True
while enthusiasm is True:
r = requests.get("https://opentdb.com/api.php?amount=1&category=9&type=multiple")
question = json.loads(r.text)
first = question['results'][0]['correct_answer']
second = question['results'][0]['incorrect_answers'][0]
third = question['results'][0]['incorrect_answers'][1]
fourth = question['results'][0]['incorrect_answers'][2]
print("--------------------------------------------------------")
print("Question number " + str(q_num)+ ":")
print(html.unescape(question['results'][0]['question']))
options = [first,second,third,fourth]
random.shuffle(options)
for X in options:
print(html.unescape(X))
legend = (
(options[0], 1),
(options[1], 2),
(options[2], 3),
(options[3], 4)
)
error = False
while error is False:
guess = input("Please enter the number of your answer(1-4):")
try:
guess = int(guess)
except:
print("Your answer must be a number between 1-4.")
continue
if guess <1 or guess > 4:
print("Your answer must be a number between 1-4.")
continue
else:
error = True
if (first, guess) in legend:
score += 1
q_num += 1
print("Correct! \nCurrent score: " +str(score))
acid = True
while acid is True:
yesno=input("Would you like another question? (y/n)")
try:
yesno = str(yesno.lower())
except:
print("Invalid input. Please enter y/n.")
continue
if yesno.lower() != "y" and yesno.lower() != "n":
print("Invalid input. Please enter y/n.")
continue
elif yesno.lower() == "y":
break
else:
acid=False
error=True
continue
else:
print("Incorrect! Better hit the books, buddy! \nCurrent score: " +str(score))
q_num += 1
acid = True
while acid is True:
yesno=input("Would you like another question? (y/n)")
try:
yesno = str(yesno.lower())
except:
print("Invalid input. Please enter y/n.")
continue
if yesno.lower() != "y" and yesno.lower() != "n":
print("Invalid input. Please enter y/n.")
continue
elif yesno.lower() == "y":
break
else:
acid=False
error=True
continue
You have two while loops:
while enthusiasm is True:
and
while error is False
Let's look at what happens when you ask if the user wants another question (simplified a little):
yesno=input("Would you like another question? (y/n)")
if yesno.lower() == "y":
break
else:
error=True
You set error to True, but you do not set enthusiasm to False, so the loop starts again at the top. Looking further, enthusiasm never gets set to False, so that condition will always start over. Simply writing
else:
error = True
enthusiasm = False
would be fine. I also would recommend thinking about if you want two loops, and what the purpose of the enthusiasm variable is.
There's a lot of other refactoring that can be done here, but not that you probably should write
while not error:
instead of explicitely checking if error "is" False. Similarly,
while enthusiasm:
is a good check on a boolean
Similarly,
yesno=input("Would you like another question? (y/n)")
try:
yesno = str(yesno.lower())
except:
print("Invalid input. Please enter y/n.")
continue
if yesno.lower() != "y" and yesno.lower() != "n":
can be improved. You don't need to cast yesno to a string, becuase that's what happens when it comes from input. You don't need the try/except either (you may have taken this from an int cast, elsewhere). Since you've already converted yesno to lower once, you don't need to keep doing that every time you compare it to a y or n.
Possible to stop the program with:
import sys
sys.exit()

Trying to have a Python program quit with the letter "q", but input is an integer? [duplicate]

This question already has answers here:
Loop until a specific user input is received in Python [duplicate]
(3 answers)
Closed 4 years ago.
A quick snippet of the code below. I tried messing around with another answer posted on here, but it didn't seem to work at all. I'm not sure what I'm doing wrong. Using Python 3 on Xubuntu 18.04 LTS. Here's the code:
while True:
try:
print("Your room is DARK, yet a light flashes red. What do you do?")
print("")
print("1. Look around.")
print("2. There's a lamp somewhere...")
print("3. Go back to bed.")
print("")
ans = int(input(">>> "))
if ans == 1:
print("")
print("Too dark to see... better find a light...")
time.sleep(2)
if ans == 2:
print("")
print("Fumbling, you turn on your nightstand lamp...")
break
if ans == 3:
print("")
print("You sleep away the troubles... but you can't stay asleep...")
time.sleep(1)
print("")
print("Back to the world of the living...")
if ans == str('q'):
sys.exit(0)
except ValueError:
print("")
So, when the user inputs "q", I want the program to close. I can't seem to get it to do it at all.
The problem is with your line where you say int(input(">>> ")) which is converting what the user enters to an integer each time. What you should do is take in the user input as a string and then check if it is a valid number for 1, 2, & 3 or if it equals q.
Example:
ans = input(">>> ")
if ans == '1':
# Do something
elif ans == '2':
# Do something
elif ans == '3':
# Do something
elif ans == 'q':
sys.exit(0)
You're typecasting the q to an integer at input: ans = int(input(">>> ")) and then trying to typecast it back to a string at if ans == str('q'): Better solution would be to keep the input as a string in ans (remove the int() typecast and explicitly typecast it as an int with int() in each case.
Update: My original solution was wrong. The corrected one asks if the string is a digit and then evaluates it as an int. This is more verbose and I therefore recommend Karl's solution. But in case you're wedded to typecasting the string as an int I'm leaving this posted.
while True:
try:
ans = input(">>> ")
if ans.isdigit() and int(ans) == 1:
...
elif ans.isdigit() and int(ans) == 2:
...
elif ans.isdigit() and int(ans) == 3:
...
elif ans == 'q':
sys.exit(0)
except ValueError:
print("")
Then you don't even need to call str() at all.

I want to setup a would you like to retry

I have created a guess the number game, at the end of it I want it to ask the user if they would like to retry. I got it to take invalid responses and if Yes then it will carry on, but when I say no it still carries on.
import random
from time import sleep
#Introduction & Instructions
print ("Welcome to guess the number")
print ("A random number from 0 - 1000 will be generated")
print ("And you have to guess it ")
print ("To help find it you can type in a number")
print ("And it will say higher or lower")
guesses = 0
number = random.randint(0, 1)#Deciding the number
while True:
guess = int (input("Your guess: "))#Taking the users guess
#Finding if it is higher, lower or correct
if guess < number:
print ("higher")
guesses += 1
elif guess > (number):
print ("lower")
guesses += 1
elif guess == (number):
print ("Correct")
print (" ")
print ("It took you {0} tries".format(guesses))
#Asking if they want another go
while True:
answer = input('Run again? (y/n): ')
if answer in ('y', 'n'):
break
print ('Invalid input.')
if answer == 'y':
continue
if answer == 'n':
exit()
First of all, when you check :
if answer in ('y','n'):
This means that you are checking if answer exists in the tuple ('y','n').
The desired input is in this tuple, so you may not want to print Invalid input. inside this statement.
Also, the break statement in python stops the execution of current loop and takes the control out of it. When you breaked the loop inside this statement, the control never went to the printing statement or other if statements.
Then you are checking if answer is 'y' or 'n'. If it would have been either of these, it would have matched the first statement as explained above.
The code below will work :
#Asking if they want another go
while True:
answer = input('Run again? (y/n): ')
if answer == 'y':
break
elif answer == 'n':
exit()
else:
print ('Invalid input.')
continue
Also, you might want to keep the number = random.randint(0, 1)#Deciding the number statement inside the while loop to generate a new random number everytime the user plays the game.
This is because of the second while loop in your code. Currently when you put y or n it will break and run again (you don't see the invalid message due to the break occurring before reaching that code), it should be correct if you change it to the following:
while True:
answer = input('Run again? (y/n): ')
# if not answer in ('y', 'n'):
if answer not in ('y', 'n'): # edit from Elis Byberi
print('Invalid input.')
continue
elif answer == 'y':
break
elif answer == 'n':
exit()
Disclaimer: I have not tested this but it should be correct. Let me know if you run into a problem with it.

How can I make it so the user can input different answers but display the same result? [duplicate]

This question already has answers here:
Comparing a string to multiple items in Python [duplicate]
(3 answers)
Closed 7 years ago.
I'm wondering how I could display the same result if the user inputs two specific answers in the input command (ie 'end' and 'End').
Here's the code I have so far; everything is working except the "end" part:
def password(): #defines password
print("Please input your password.")
pass2 = input("Password: ")
if pass2 == ("abcd123"):
print("Thank you for using Efficient Systems, Co.")
end = input("Type end to exit: ")
while True:
if end == ("end") and ("End"):
break
else:
print("Invalid command.")
end = input("Type end to exit: ")
else:
print("Invalid command.")
time.sleep(1)
pass2 = input("Password: ")
I think it's worth noting that if I do type in 'end', it goes back to pass2.
The condition is wrong -
if end == ("end") and ("End"):
This would only evaluate to true (when end is 'end' ), because this would get translated as -
if ((end == "end") and "End")
And any non-empty string in python is True-like (has true value in boolean context.)
To check for all cases, best thing to do would be to check your variable's .lower() with 'end' , example -
if end is not None and end.lower() == "end":
And since you are taking input using input() function, you actually do not need the is not None part, so you can do -
if end.lower() == "end":
You need to use or:
if end == "end" or end == "End":
....
if you want to check the string case-insensitive, use str.casefold:
if end.casefold() == "end":
...

Categories