Menu prompt doesn't work - python

I have written an application in Python to work with strings, i made a menu prompt from which i can select an operation to do, i tested all the functions, they work well, except the menu and main functions, that when i enter my choice nothing happens. Here's the code:
import re
import os
def searchInFile(searched, file):
try:
f = open(file)
except IOError.strerror as e:
print("Couldn't open the file: ", e)
else:
sea = re.compile(searched, re.IGNORECASE)
for line in f:
if re.search(sea, line):
print(line, end='')
def validateWithPattern(string):
patt = re.compile('([a-z0-9-_.])+#([a-z]+.)([a-z]{2,3})', re.IGNORECASE)
if re.search(patt, string):
print("Valid")
else:
print("Not valid!")
def menu():
print("|================MENU=================|\n", end='')
print("|0- Exit the program |\n", end='')
print("|1- Validate mail address |\n", end='')
print("|2- Search a string in a file |\n", end='')
print("|=====================================|\n", end='')
b = input("->")
return b
def main():
b = 10
while b != 0:
b = menu()
if b == 1:
a = input('Enter you mail address: ')
validateWithPattern(a)
elif b == 2:
a = input('Enter the file name: ')
c = input('Enter the string: ')
searchInFile(c, a)
elif b == 0:
os.system("PAUSE")
else: print("Choice error")
if __name__ == "__main__":
main()

Your b variable you are returning from menu function is a string, not an integer, so you can't compare it with numbers (input is automatically saved as string). If you use return int(b) instead of return b, it will be ok.
Also, I think your else: print("Choice error") should be indented the same way your if and elif are, since you probably want to write "Choice error" only if b is not one of given choices. The way it is indented in your code will print "Choice error" after the while loop ends and it will not print that message if you input the value it can't recognize (for example 3).

Related

I need with perfecting a project for beginners in terms of writing to a file

I'm trying to make sure the input the user uses is all letters.I tried the .alpha method but since this is a file, a "." will be included returning it false. I also tried using "quit" sentinel value to exit the program but that isn't working. It keeps saying break is outside the loop. I also want the user to keep inputting if the file is not found error is raised.
The Assignment1
def main():
fileName = inputTxt()
FiletoReadFrom = openingFile(fileName)
counter = 0
for line in FiletoReadFrom:
outputFile = open("output.txt", "a+")
counter = counter + 1
outputFile.write("/* {} */ {}\n".format(counter, line.strip()))
if counter == 0:
print("This is an empty file")
else:
print("The file has been made")
FiletoReadFrom.close()
outputFile.close()
def inputTxt():
flag = True
while flag == True:
FileName= input("Please Enter the Name of the File, or type quit to exit ")
if FileName == quit:
flag == False
break
print("goodbye")
else:
return FileName
def openingFile(filetoReadFrom):
try:
a = open(filetoReadFrom, 'r')
return a
except FileNotFoundError:
print("This File was not Found", "Enter again or type quit to exit")
main()
There are different questions here, which is frowned upon on this site. Please never do that again.
the quit and break problem:
It is just a typo. As you forgot quoting 'quit', Python sees it at an undeclared variable which gives a syntax error. Fix:
...
while flag == True:
FileName= input("Please Enter the Name of the File, or type quit to exit ")
if FileName == 'quit':
flag == False
break
...
But it is still wrong, because break will only exit from the loop and inputTxt will return None which is not what you expect. Calling sys.exit() could be better here.
Test for letters and not numbers:
You must choose a white list (only alphas and dot) or black list (no numbers) way. In idiomatic Python it could be:
if all((x.isalpha() or x == '.') for x in FileName): # white list
# process error condition
if any(x.isdigit() for x in FileName): # black list
# process error condition
You could also use the re module which is great at controlling that a string respect a given pattern...
keep asking until a valid file is given:
You should use a loop:
def main():
while True:
fileName = inputTxt()
FiletoReadFrom = openingFile(fileName)
if FileToReadFrom is not None: # openingFile returns None when file does not exist
break
But IMHO, you should remove the openingFile function and directly use (and test) open in main

problem with Input() function when don`t want user enter number

i wrote an script , i want to know how to prevent when user enter number i show a message 'number is not OK! just string') .
Thanks.
#! /usr/bin/ipython3
a=input('Please enter your Name : ')
if a=='mohammadreza':
print(" ")
print ('i found you finally')
print(" ")
elif a=='':
print ('Null name is not ok!')
else:
print ('No you are not that person')
You have a string. And if you want to check if it is a number, you can use the following code:
a.replace('.','',1).isdigit()
So you can create a new elif like this:
elif a.replace('.','',1).isdigit():
print("number is not OK! just string")
problem here is input always return a string. isdigit handle this for you but it fails with floats (this is the reason behind "replace . solution").
Another approach could be:
#!/usr/bin/env python
def is_a_number(s):
'''try to convert a string to int and float'''
try:
int(s)
return True
except:
pass
try:
float(s)
return True
except:
pass
return False
def main():
a=input('Please enter your Name : ')
if a=='foo':
print ('i found you finally')
elif is_a_number(a):
print('number is not OK! just string')
elif a=='':
print ('Null name is not ok!')
else:
print ('No you are not that person')
if __name__ == '__main__':
main()

What is wrong with this except statement? Python 3.4.3

Code works until I try to handle the ValueError with an except statement. Returns an invalid syntax traceback.
def write():
filename = input('Please Enter the File name:') + '.txt';
with open (filename, "a") as f:
while True:
a,b = input('Enter in format Name,Carbs per 10 grams').split(',')
a = str (a)
b1 = float (b)
f.write (a+','+ b+ '\n');
except ValueError:
continue
loop = input ('Do you want to add anything else y/n:')
if loop == 'n':
break
I don't see a try statement in your code. You probably want something like this. See the docs for more examples.
while True:
try:
a,b = input('Enter in format Name,Carbs per 10 grams').split(',')
a = str (a)
b1 = float (b)
f.write (a+','+ b+ '\n');
except ValueError:
continue
You need to have a try statement to have an except statement.
def write():
filename = input('Please Enter the File name:') + '.txt';
with open (filename, "a") as f:
while True:
try: #added try statement
a,b = input('Enter in format Name,Carbs per 10 grams').split(',')
a = str (a)
b1 = float (b)
f.write (a+','+ b+ '\n');
except ValueError:
continue
loop = input ('Do you want to add anything else y/n:')
if loop == 'n':
break

What is wrong with my defintion of the function prompt_int?

I have been trying to program a maths quiz that both works and is as efficient as possible. Looking over my code I saw I had a lot of integer inputs and that lead to me having the program to ask the question/exit the system if the criteria isn't met, so to help me I thought that it would be useful to create a new function. Here is my attempt:
def prompt_int(prompt=''):
while True:
if status == prompt_int(prompt=''):
val = input(prompt)
if val in (1,2):
return int(val)
return true
elif status != prompt_int(prompt=''):
val = input(prompt)
if val in (1,2,3):
return int(val)
return true
else:
print("Not a valid number, please try again")
However, when I try to implement this function around my code it doesn't work properly as it says that status isn't defined however, when I do define status it goes into a recursion loop. How can I fix this problem?
Here is my original code before i try to implement this function:
import sys
import random
def get_bool_input(prompt=''):
while True:
val = input(prompt).lower()
if val == 'yes':
return True
elif val == 'no':
return False
else:
sys.exit("Not a valid input (yes/no is expected) please try again")
status = input("Are you a teacher or student? Press 1 if you are a student or 2 if you are a teacher")# Im tring to apply the new function here and other places that require integer inputs
if status == "1":
score=0
name=input("What is your name?")
print ("Alright",name,"welcome to your maths quiz."
"Remember to round all answer to 5 decimal places.")
level_of_difficulty = int(input(("What level of difficulty are you working at?\n"
"Press 1 for low, 2 for intermediate "
"or 3 for high\n")))
if level_of_difficulty not in (1,2,3):
sys.exit("That is not a valid level of difficulty, please try again")
if level_of_difficulty == 3:
ops = ['+', '-', '*', '/']
else:
ops = ['+', '-', '*']
for question_num in range(1, 11):
if level_of_difficulty == 1:
number_1 = random.randrange(1, 10)
number_2 = random.randrange(1, 10)
else:
number_1 = random.randrange(1, 20)
number_2 = random.randrange(1, 20)
operation = random.choice(ops)
maths = round(eval(str(number_1) + operation + str(number_2)),5)
print('\nQuestion number: {}'.format(question_num))
print ("The question is",number_1,operation,number_2)
answer = float(input("What is your answer: "))
if answer == maths:
print("Correct")
score = score + 1
else:
print ("Incorrect. The actual answer is",maths)
if score >5:
print("Well done you scored",score,"out of 10")
else:
print("Unfortunately you only scored",score,"out of 10. Better luck next time")
class_number = input("Before your score is saved ,are you in class 1, 2 or 3? Press the matching number")
while class_number not in ("1","2","3"):
print("That is not a valid class, unfortunately your score cannot be saved, please try again")
class_number = input("Before your score is saved ,are you in class 1, 2 or 3? Press the matching number")
else:
filename = (class_number + "txt")
with open(filename, 'a') as f:
f.write("\n" + str(name) + " scored " + str(score) + " on difficulty level " + str(level_of_difficulty))
with open(filename, 'a') as f:
f = open(filename, "r")
lines = [line for line in f if line.strip()]
f.close()
lines.sort()
if get_bool_input("Do you wish to view previous results for your class"):
for line in lines:
print (line)
else:
sys.exit("Thanks for taking part in the quiz, your teacher should discuss your score with you later")
if status == "2":
class_number = input("Which classes scores would you like to see? Press 1 for class 1, 2 for class 2 or 3 for class 3")
if class_number not in (1,2,3):
sys.exit("That is not a valid class")
filename = (class_number + "txt")
with open(filename, 'a') as f:
f = open(filename, "r")
lines = [line for line in f if line.strip()]
f.close()
lines.sort()
for line in lines:
print (line)
Well, just a part:
def prompt_int(prompt=""):
while True:
val = input(prompt)
if val in ("1", "2"):
return int(val), True
Will ask again and again. And return when the user enter "1" or "2"!
But better: "if val in "12":
def prompt_int(prompt=""):
while True:
val = input(prompt)
if val.isdigit():
return int(val)
Hi if you dont want to have valid values send to your you could change your code as the function above.
But you could also change it to do the system exits:
def prompt_int(prompt="", authorized=()):
while True:
val = raw_input(prompt)
if val.isdigit():
if int(val) in authorized:
return int(val)
else:
sys.exit("Bla bla bla too bad")
def prompt_int(prompt=''):
while True:
if status == prompt_int(prompt=''):
This line will look for the name "status" in the global namespace (module's namespace), and raise a NameError if there's no global variable named 'status'.
If there's one, it will then recursively calls prompt_int without any possible termination, resulting theoretically in an endless recursion, but practically (in CPython at least) in a RuntimeError when it will hit the maximum recursion depth.
There are also quite a few other things that won't work as you expect:
val = input(prompt)
if val in (1,2):
In Python 3.x, val will be a string, so it will never compare equal to an int. In Python 2.x, input() is a shortcut for eval(raw_input()), which might return an int, but is also a huge security flaw since it unconditionnally execute untrusted code.
return int(val)
return true
The second return statement will never be executed, obviously, since the function will exit at the first one.
A simpler implementation might look like this:
# rebinds raw_input to input for python < 3
import sys
if sys.version_info.major < 3:
input = raw_input
def prompt_int(prompt='', choices=None):
while True:
val = input(prompt)
try:
val = int(val)
if choices and val not in choices:
raise ValueError("{} is not in {}".format(val, choices))
return val
except (TypeError, ValueError) as e:
print(
"Not a valid number ({}), please try again".format(e)
)
While we're at it, there's room for improvement in other parts of your code. Let's start with this:
def get_bool_input(prompt=''):
while True:
val = input(prompt).lower()
if val == 'yes':
return True
elif val == 'no':
return False
else:
sys.exit("Not a valid input (yes/no is expected) please try again")
First point: your naming is not consistent. If your other function is named prompt_int, this one should be named prompt_bool. Also, you have one function (prompt_int) looping forever and the other one exiting the whole program on invalid input, which is another inconsistency. If you want to allow the user to exit on any prompt, provide an explicit option for it, ie:
def prompt_bool(prompt, quit='Q'):
prompt += " (hit '{}' to exit) : ".format(quit)
while True:
val = input(prompt).strip().upper()
if val == quit:
sys.exit("Goodbye")
elif val == 'yes':
return True
elif val == 'no':
return False
else:
print "Invalid input '{}', please try again".format(val)
Of course you then want to provide the same option in prompt_int(), which leads to a more generic function:
def get_input_or_quit(prompt, quit="Q"):
prompt += " (hit '{}' to exit) : ".format(quit)
val = input(prompt).strip()
if val.upper() == quit:
sys.exit("Goodbye")
return val
def prompt_bool(prompt):
while True:
val = get_input_or_quit(prompt).lower()
if val == 'yes':
return True
elif val == 'no':
return False
else:
print "Invalid input '{}', please try again".format(val)
And of course you also replace the call to input by a call to get_input_or_quit in prompt_int.
We could go on for long - splitting all your code in distinct, self-contained function, writing a "main()" function to drive them (instead of having the "main" part at the top level), and obviously using the operator module instead of eval().

How to prevent command window from closing when a program finishes executing

I made a small program in Python (.py) and converted it into a Windows executable file (.exe) using Py2exe. It asks for a string and then outputs a string -- very simple! -- and works flawlessly in Python.
However, when the exe file finishes execution in the command window, the command window closes automatically before I can get a glimpse of its output (I assume it does print the output because, like I said, it works flawlessly in Python).
How can I prevent this from happening? I assume I need to change my code, but what exactly do I need to add to it?
Here is my code, in case it helps you to see it (it's a word-wrapper):
import string
def insertNewlines(text, lineLength):
if text == '':
return ''
elif len(text) <= lineLength:
return text
elif text[lineLength] == ' ':
return text[:lineLength] + '\n' + insertNewlines(text[lineLength+1:], lineLength)
elif text[lineLength-1] == ' ':
return text[:lineLength] + '\n' + insertNewlines(text[lineLength:], lineLength)
else:
if string.find(text, ' ', lineLength) == -1:
return text
else:
return text[:string.find(text,' ',lineLength)+1] + '\n' + insertNewlines(text[string.find(text,' ',lineLength)+1:], lineLength)
print
if __name__ == '__main__':
text = str(raw_input("Enter text to word-wrap: "))
lineLength = int(raw_input("Enter number of characters per line: "))
print
print insertNewlines(text, lineLength)
Thank you.
The simplest way is probably to use raw_input() just before your program finishes. It will wait until you hit enter before closing.
if __name__ == '__main__':
text = str(raw_input("Enter text to word-wrap: "))
lineLength = int(raw_input("Enter number of characters per line: "))
print
print insertNewlines(text, lineLength)
raw_input()
Just put this at the end of your code:
junk = raw_input ("Hit ENTER to exit: ")
In other words, your main segment should be:
if __name__ == '__main__':
text = str(raw_input("Enter text to word-wrap: "))
lineLength = int(raw_input("Enter number of characters per line: "))
print
print insertNewlines(text, lineLength)
junk = raw_input ("Press ENTER to continue: ")
This is what I use in my scripts:
#### windows only ####
import msvcrt
def readch(echo=True):
"Get a single character on Windows."
while msvcrt.kbhit():
msvcrt.getch()
ch = msvcrt.getch()
while ch in b'\x00\xe0':
msvcrt.getch()
ch = msvcrt.getch()
if echo:
msvcrt.putch(ch)
return ch.decode()
def pause(prompt='Press any key to continue . . .'):
if prompt:
print prompt,
readch()
######################
Sometimes though, I just use the following to make the window stay open for a short time before closing.
import time
time.sleep(3)

Categories

Resources