Executing menu() and go to 1 or 2 or 3 is good to do its work.
But after passing by getproduct(character) and getting back to menu() and then if you choose number 3, it makes a bad loop.
I want to know why, and how to solve this problem...
def menu():
menu = '1. ice\n2. cream\n3. quit'
print(menu)
try:
order = int(input('choose one: '))
if order == 1:
c = 'ice'
getproduct(c)
elif order == 2:
c = 'cream'
getproduct(c)
elif order == 3:
exit()
else: menu()
except ValueError: menu()
def getproduct(character):
toping = int(input('1. ice or 2. cream?'))
try:
if character == 'ice' and toping == 1:
print(character + 'ice')
menu()
elif character == 'ice' and toping == 2:
print(character + 'cream')
menu()
elif character == 'cream' and toping == 1:
print(character + 'ice')
menu()
elif character == 'cream' and toping == 2:
print(character + 'cream')
menu()
else: getproduct(character)
except: getproduct(character)
menu()
There are several mistakes on the code. First of all, you are using exit, that should not be used within files, instead of it, I use on my example the module sys (sys.exit(0)) that has the same goal.
On the other hand, you are using the input checks in an imprecise way, and looping should be different. In menus, I personally recommend using while loops.
Solution for your problem and a a couple of improvements (could be better):
import sys
def menu():
menu = '1. ice\n2. cream\n3. quit'
while True:
print(menu)
try:
order = int(input('choose one: '))
except:
print("Use a correct answer")
else:
if order == 1:
c = 'ice'
getproduct(c)
elif order == 2:
c = 'cream'
getproduct(c)
elif order == 3:
sys.exit(0)
else:
print("Use a correct answer")
def getproduct(character):
topings = '1. ice or 2. cream?: '
while True:
print(topings)
try:
second_order = int(input())
except:
print("Use a correct answer")
else:
if character == 'ice' and second_order == 1:
print(character + 'ice')
break
elif character == 'ice' and second_order == 2:
print(character + 'cream')
break
elif character == 'cream' and second_order == 1:
print(character + 'ice')
break
elif character == 'cream' and second_order == 2:
print(character + 'cream')
break
else:
print("Use a correct answer.")
menu()
The exit() function works by raising the SystemExit type of exception, which propagates up the chain until there's nothing more to run and the program comes to a stop.
That it is an exception means that the code above where the SystemExit is raised is allowed to close resources and do other wind-down activities, so as not to break any external resources. However, it also means that a blank except: statement can catch the SystemExit and ignore it. Which is what's happening here.
def getproduct(character):
toping = int(input('1. ice or 2. cream?'))
try:
...
# call to menu(), which calls exit()
except: # this activates on ANY exception, including SystemExit
getproduct(character)
In general, you should almost never use a raw except block, because of situations like this where it catches something you don't want it to. Instead, analyze the code inside the try, figure out what types of exceptions it would throw, and catch those. In your case, it's likely to be either ValueError or TypeError:
try:
...
except (ValueError, TypeError):
getproduct(character)
or, if you're dead set on catching everything, you can write a special exception for if the error is a SystemExit (though, again, a blank except: or a except Exception: is considered bad practice):
try:
...
except SystemExit:
pass # ignore it
except:
getproduct(character)
You should note, according to the documentation:
quit(code=None)
exit(code=None)
Objects that when printed, print a message like “Use quit() or Ctrl-D (i.e. EOF) to exit”, and when called, raise SystemExit with the specified exit code.
You should probably use sys.exit() instead, though it does basically the same thing.
Related
I'm aware of the sympy module in python and I know how to use it most of the time, however, I need to append different values to a list and then join it into a string. I need to append the superscript 'x' at the end of the list. Here's my code:
from functions import *
from subprocess import run
from sympy import pretty_print as pp
from sympy.abc import x
try:
run("clear", shell=True)
print("\033[92m[*] Initializing Exponential Equation Calculator", end='', flush=True)
print_dots(3)
while True:
print("\n\n================================Select Option================================")
print("1. Create exponential equation\n2. Calculate exponential growth\n3. Calculate exponential decay\n4. Exit")
try:
option = int(input(">>> "))
except ValueError:
handle_error("Please enter an option from above")
continue
if option == 1:
equation = ["y = "]
while True:
points_table = get_points()
for j in points_table:
i = 0
status = 0
while i < len(j):
if j[i] == 0:
yInt = j[i + 1]
status += 1
break
i += 1
if status == 1:
break
growth_rate = find_pattern(points_table)
if growth_rate is None:
handle_error("There is no exponential pattern in the table provided. Try again", 1)
continue
equation.append(str(yInt))
equation.append(" * ")
equation.append(str(growth_rate))
result = ''.join(equation)
print(f"\033[93m[*] Equation Calculated! The equation is \033[96m{result}\033[92m")
sleep(2)
while True:
try:
print("================================Select Option================================")
print("Would you like to:\n\n1. Calculate another equation\n2. Choose a different option\n3. Exit")
choice = int(input(">>> "))
if choice == 1 or choice == 2:
break
elif choice == 3:
raise KeyboardInterrupt
else:
handle_error("Please enter a valid option")
continue
except ValueError:
handle_error("Please enter a valid option")
continue
if choice == 2:
break
elif option == 2:
pass
elif option == 3:
pass
elif option == 4:
raise KeyboardInterrupt
else:
handle_error("Please enter an option from above")
continue
break
except KeyboardInterrupt:
print("\n\033[96m[*] Shutting down...\n\033[0m")
exit(0)
In the lines where there's 3 append functions, I don't know how I'm supposed to add the superscript 'x' to the end of the list. Can someone help me please?
I'm making a small number guessing game, and have defined a function to ask a yes/no question:
def again(question):
quit_loop = False
while quit_loop == False:
try:
again = str(input("\n" + question + " [y/n] ")).lower().strip()
except KeyboardInterrupt:
quit("\nAbort! Abort!\n")
except:
print("You have to enter something...")
continue
else:
if again[0] == 'y':
return True
elif again[0] == 'n':
return False
else:
print("Please enter either y or n...")
It runs fine, except for one thing. At the input prompt, if you don't type anything and just press return, you get the following error:
Traceback (most recent call last):
File "guess.py", line 112, in <module>
main_game(number, guess, prev_guesses)
File "guess.py", line 109, in main_game
guess_again(number, guess, prev_guesses)
File "guess.py", line 58, in guess_again
guess_again = again("Would you like to give it another go?")
File "guess.py", line 77, in again
if again[0] == 'y':
IndexError: string index out of range
I've put in the except: block to try and handle this error, but it doesn't work. I'm obviously doing something wrong, but I've spend ages on this and it has me stumped!
Is anyone able to point out where I've gone wrong and how to make it work as intended please?
When you enter in nothing you have again = '' as there is no error with an input of nothing. In line 77 you then try and get the 0th index (first character) of the string 'again', but it has a length of 0 and so there is an index out of range error.
In order to see if they have entered in nothing, simply do the check
if again == "":
Print("You need to enter something")
Or in this case, something like:
if again[0] != "y" or again[0] != "n":
Print("Please enter y/n")
By my understanding your error occurs here:
if again[0] == 'y':
return True
elif again[0] == 'n':
return False
else:
print("Please enter either y or n...")
In
again = str(input("\n" + question + " [y/n] ")).lower().strip()
If there is no input, when you run
if again[0] == 'y'
there is no again[0] because again is empty. Hence, Index error: string out of range.
To fix this make sure that again is not empty before you check if its first letter is y or n. If again is empty, it is not an error, so try will not catch it.
Please try something like that:
if again and again[0] == 'y':
return True
elif again and again[0] == 'n':
return False
else:
print("Please enter either y or n...")
When you press enter, you input an empty input, so it does not raise any exceptions and passes to else clause, where you try to access element 0 of empty again which throws error. You can check for again content before calling again[0]. Try:
def again(question):
quit_loop = False
while quit_loop == False:
try:
again = str(input("\n" + question + " [y/n] ")).lower().strip()
except KeyboardInterrupt:
quit("\nAbort! Abort!\n")
except:
print("You have to enter something...")
continue
else:
if not again:
print("You have to enter something...")
continue
elif again[0] == 'y':
return True
elif again[0] == 'n':
return False
else:
print("Please enter either y or n...")
You also do not need else statement here. You can make it neater like:
def again(question):
quit_loop = False
while quit_loop == False:
try:
again = str(input("\n" + question + " [y/n] ")).lower().strip()
if not again:
print("You have to enter something...")
continue
elif again[0] == 'y':
return True
elif again[0] == 'n':
return False
else:
print("Please enter either y or n...")
except KeyboardInterrupt:
quit("\nAbort! Abort!\n")
except:
print("You have to enter something...")
continue
I check to see if input can be changed into an integer if it can't it starts back from the beginning of UI(). I followed it through pycharm's debugger and it will pass the try, but when I try using 4 to exit.It will go through to the end, and then go back up to the except block.
I think the parts I commented after are the only relevant parts. Thanks for any help.
def UI():
global exitBool
global newBool
if not TV.tvList:
tv = TurnOnTV()
if TV.tvList:
l = list(TV.tvList.keys())
tv = TV.tvList.get(l[0])
print("1)change channel\n2)change volume\n3)Turn on another TV\n4)Exit\n5)Choose TV") #print accepted answers
choice = input()
try:
choice = int(choice) #try block and exception block
except:
print("\nInvalid Choice\n")
UI()
choice = int(choice)
if choice == 1:
if tv:
tv.changechannel(input("enter channel: "))
else:
print('sorry no tvs are available\n')
elif choice == 2:
if tv:
tv.changevolume(input("Enter in volume: "))
else:
print('Sorry no Tvs available')
elif choice == 3:
TurnOnTV()
elif choice == 4:
exitBool = True # exit bool to exit main loop
elif choice == 5:
tv = ChooseTV(input("Enter in TV name: "))
else:
print("Invalid Choice")
if tv:
tv.display()
def Main():
while exitBool == False: #Main Loop
UI()
When you catch the error and print "invalid choice" you must not call UI() again. That way you are making a recursive call, and when the inner UI() terminates the code goes on on the outer one.
Use a "while" statement to repeat a block of code until the user makes a valid choice.
I am a beginner Python programmer (Python 3) and I just made my first real working program. I encounter an issue with the try: except: part (ln 63), I can't manage to trigger the range_error condition in the usr_input() function. I'm probably not using exceptions the right way.
from random import randint
def gen_num():
magic_num = randint(1,100)
return magic_num
def usr_input(range_error = False):
if range_error == True: # If number is out of range, displays additionnal warning message
print("Make sure you enter a number between 1 and 100 !")
usr_num_guess = input("Please enter an integer between 1 and 100 : ")
return int(usr_num_guess)
def play_again():
# We ask the user to choose if he wants to play again or not (yes / no)
yes = set(['yes','y','ye','yeah',''])
no = set(['no','n'])
usr_choice = input("Do you wish t play again ? (Y/n):").lower()
if usr_choice in yes:
return True
elif usr_choice in no:
return False
else:
sys.stdout.write("Please write 'yes' or 'no'")
def player_level_initialize():
# Setting up the user's desired level
easy_level = set(['easy',1])
med_level = set(['medium','med',2,''])
hard_level = set(['hard','difficult',3])
level_choice = input("Please select your level (easy,MED,hard) :").lower()
if (level_choice in easy_level):
return "easy"
elif (level_choice in med_level):
return "med"
elif (level_choice in hard_level):
return "hard"
else:
sys.stdout.write("Please write 'easy', 'med' or 'hard'")
print("Hello and Welcome to this awesome game !")
player_name = input("Please enter your name : ")
level = player_level_initialize()
keep_playing = True
usr_score = 0
while (keep_playing == True):
num_to_guess = gen_num()
num_of_attempts = 1
too_m_attempts = False
max_number_of_attempts = {
"easy":10,
"med":6,
"hard":3
}
usr_num_guess = usr_input()
while (too_m_attempts == False or usr_num_guess != num_to_guess):
if (num_of_attempts < max_number_of_attempts[level]):
try:
(usr_num_guess >= 1 and usr_num_guess < 100)
except:
usr_num_guess = usr_input(True) # If the input number is out of range, the player gets a warning message + new input
else:
if (usr_num_guess != num_to_guess):
if (usr_num_guess < num_to_guess):
print("It's more !")
else:
print("It's less !")
num_of_attempts += 1
usr_num_guess = usr_input()
elif (usr_num_guess == num_to_guess):
usr_score += 1
print("Good job", player_name, "you found the magic number in only", num_of_attempts, "attempts ! It was", num_to_guess, "You have a current score of", usr_score)
else:
print("Sorry, too many attempts ! The magic number was", num_to_guess)
too_m_attempts = True
keep_playing = play_again()
print("Thank you ! I hope you enjoyed the game !")
What you need is an if block instead of a try-except block:
if not (usr_num_guess >= 1 and usr_num_guess < 100):
usr_num_guess = usr_input(True) # If the input number is out of range, the player gets a warning message + new input
The code in the except part will only be executed if the line (usr_num_guess >= 1 and usr_num_guess < 100) raises an exception.
On the use of exception, when you write
try:
...
except:
...
the code will catch every possible exception and execute th code in the except block which is supposed to fix the situation. This is probably not what you want most of the time. For example, mis-spelling a variable (e.g. usr_num_guesss) will raise a NameError, and whatever user_input() do will not fix the error -- it is an entirely different problem already than an out-of-range input. You should only catch and handle the exceptions that can be handled by your code, such as:
except ValueError:
...
Sorry quite new to python in the grand scheme of things, basically I want to be able to have an input screen that users have a selection of choices, when a choice has been made a command will run, then give the user the option to go back to the choices to choose another one, or to exit the program completely.
Currently I have
print ("1.")
print ("2.")
print ("3.")
errorch=0
while not errorch :
try :
choice = int ( input('Please Choose from Options below :') )
errorch = 1
except ValueError as e :
print ("'%s' is not a valid integer." % e.args[0].split(": ")[1])
if choice == 1:
print ("CODE:")
elif choice == 2:
print ("OTHER:")
elif choice == 3:
print ("OTHER:")
else:
print ("Invalid Choice. Please Try Again:")
k=input('Press close to exit')
In each choice I do have code that runs, but to save space I have omitted this
Use a while loop.
while True: # this loop runs forever
print("1.")
...
print("4.") # this is for exit
# get input
if choice == 1:
...
# if choice is 4, then break out of this loop
elif choice == 4:
break # breaks out of the loop
else:
...
You can just wrap the whole thing in another while loop:
while True:
...
if k.lower() == "close":
break
You can use this same form to make your existing loop neater, removing the errorch flag:
while True:
try:
choice = int(input('Please Choose from Options below :'))
except ValueError as e :
print ("'%s' is not a valid integer." % e.args[0].split(": ")[1])
else:
break