CS50 taqueria task - input of eof halts program - python

I am trying to solve the taqueria task for the Harvard CS50 python course. It generally works, but check50 spits out the following:
:( input of EOF halts program
Cause
expected exit code 0, not 1
This is my code:
menu = {
"Baja Taco": 4.00,
"Burrito": 7.50,
"Bowl": 8.50,
"Nachos": 11.00,
"Quesadilla": 8.50,
"Super Burrito": 8.50,
"Super Quesadilla": 9.50,
"Taco": 3.00,
"Tortilla Salad": 8.00
}
def main():
item = get_dish("Item: ")
total = 0
try:
while True:
try:
total += menu[item.title()]
print("$" + str(round(total, 3)))
item = get_dish("Item: ")
except KeyError:
item = get_dish("Item: ")
pass
except EOFError:
pass
def get_dish(prompt):
dish = input(prompt)
while dish.lower() in menu == False:
dish = input(prompt)
else:
return dish
main()
I cannot end input to induce an EOFError in VS Code on GitHub myself by pressing ctrl + z or ctrl + d. Therefore, I cannot handle it myself in the try... except block. It might be a problem with the VS Code itself. Maybe there are other ways to end input, induce an EORError and handle it in the code.

Method 1: provide an empty input file
You can reproduce an EOFError in your code by giving it an empty input file.
In the VSCode terminal using bash, or at a bash prompt:
$ python script_name.py < /dev/null
Item: Traceback (most recent call last):
File "C:\Users\me\sandboxes\scratch\script_name.py", line 35, in <module>
main()
File "C:\Users\me\sandboxes\scratch\script_name.py", line 14, in main
item = get_dish("Item: ")
File "C:\Users\me\sandboxes\scratch\script_name.py", line 29, in get_dish
dish = input(prompt)
EOFError: EOF when reading a line
Or if you're using the Windows cmd prompt, in a VSCode terminal or otherwise:
> python script_name.py < NUL
Item: Traceback (most recent call last):
File "C:\Users\me\sandboxes\scratch\script_name.py", line 35, in <module>
main()
File "C:\Users\me\sandboxes\scratch\script_name.py", line 14, in main
item = get_dish("Item: ")
File "C:\Users\me\sandboxes\scratch\script_name.py", line 29, in get_dish
dish = input(prompt)
EOFError
In both cases above, you could also create a file to use as input, and have it empty when that's what you want to test, but /dev/null / NUL is the bash/cmd name for the special system empty file you can always use instead of creating one.
And as you see in these traces, the problem is that your first call to get_dish() is not in a try/except block.
Method 2: interactively end the input stream
In cmd, just type ^Z+Enter and that'll trigger the EOF and reproduce the same error.
To my surprise, in bash the equivalent ^D doesn't automatically do the same thing. I expected it would, as is typical, but instead when you type ^D+Enter you get "\x04" as the string returned by input(). So I guess if your program wants to accept ^D+Enter to mean end of file, it would have to explicitly do so with a piece of logic like if dish == "\x04": raise EOFError in get_dish(), but I understand you're just trying to debug your code and reproduce the error check50 gives you, so this is not too helpful.
So... if you're working in a bash terminal, use method 1 above.
When you've got things working, you'll probably want to add something to get_dish() for the user to signify they're done, like accepting q to mean done, because as it is, your user won't be able to exit the program cleanly, at least not from a bash terminal.

Related

Assertion Error From a common.py file for code editor

(Please note: I am a beginner with Python) When I try to input my bssid it gives me an assertion error referencing a section of another file of code called common.py that I think comes with my code editor (thonny). How would I remedy this?
import os
import time
opsys = input("Are you using MacOS or Windows? ")
if (opsys.lower() == "windows"):
print("\n Alrighty, let me just open u your command prompt for you.")
time.sleep(0.5)
os.system("start /B start cmd.exe #cmd /k netsh wlan show interfaces")
time.sleep(0.25)
bssid = input("\nNow paste in the set of numbers labelled BSSID: ")
print("Thanks")
Here is the statement the assertion error is referencing from common.py:
def parse_message(msg_string: str) -> Record:
# DataFrames may have nan
# pylint: disable=unused-variable
nan = float("nan") # #UnusedVariable
assert msg_string[0] == MESSAGE_MARKER
return eval(msg_string[1:].encode("ASCII").decode("UTF-7"))
Here is the entire traceback error:
Traceback (most recent call last):
File "C:\Users\tjmon\Documents\Honors Comp Sci\Other Programs\Lab3.py", line 60, in <module>
bssid = input("\nNow paste in the set of numbers labelled BSSID: ")
File "C:\Users\tjmon\AppData\Local\Programs\Thonny\lib\site-packages\thonny\common.py", line 220, in parse_message
assert msg_string[0] == MESSAGE_MARKER
AssertionError
So in common.py its referenced as MESSAGE_MARKER = "\x02", which means something like "Start of Text"
Oct Dec Char Hex Key Comments
\000 0 NUL \x00 ^# \0 (Null byte)
\001 1 SOH \x01 ^A (Start of heading)
\002 2 STX \x02 ^B (Start of text)
Maybe it's just a error in thonny - did you try your program without it?

How to handle no input using input() function in Python?

I tried to write a program which requests user to choose an option, however, Python always show an error message if user choose nothing and only input ENTER. Here is an example
tmp=input("Choose program type:1.C++;2.Python;3.PERL (ENTER for default 2.Python)")
print tmp, type(tmp) #test input
if len(str(tmp)) == 0:
tmp=0
if tmp == 1:
print "User choose to create a C++ program.\n"
DFT_TYPE=".cpp"
elif tmp ==2:
print "User choose to create a Python program.\n"
DFT_TYPE=".py"
elif tmp ==3:
print "User choose to create a PERL scripts.\n"
DFT_TYPE=".pl"
else:
print "User choose incorrectly. Default Python program would be created.\n"
DFT_TYPE=".py"
if I input ENTER only, I got error message like below
Traceback (most recent call last): File "./wcpp.py", line 17, in <module>
tmp=input() File "<string>", line 0
^ SyntaxError: unexpected EOF while parsing
How to handle such case if user input nothing? Any further suggestion would be appreciated.
Since you are using python 2, use raw_input() instead of input().
tmp=raw_input("Choose program type:1.C++;2.Python;3.PERL (ENTER for default 2.Python)")
...
...
if tmp!='':
tmp = int(tmp)
pass #do your stuff here
else:
pass #no user input, user pressed enter without any input.
The reason you are getting error is because in python2 input() tries to run the input statement as a Python expression.
So, when user gives no input, it fails.
you can use raw_input with a default value
x = raw_input() or 'default_value'

How does a user input a filename?

I've written code for an assembler, but I am still new to python.
In my code I have the user input a file that will be converted into an assembly language. I think I've almost got it working, but I can't figure out where the user enters the file name.
I'm in (what I think is) IDLE, and then when I hit F5 it runs in the shell. I'm getting an error, but I'm pretty sure it's because no file name has been entered.
Where is the user supposed to input these kinds of things? Is this done from the python shell, or from the command line, do I need to turn it into an executable?
Can someone help clarify where the user is inputting all this information?
I'll put in a segment of code, although I don't think it's necessary to answer my questions, but maybe it'll give you a better idea of my issue.
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print 'need filename'
sys.exit(-1)
table = SymbolTable()
parser = Parser(sys.argv[1])
parser.advance()
line = 0
while parser.hasMoreCommands():
if parser.commandType() == 'L_COMMAND':
table.addEntry(parser.symbol(), line)
else:
line += 1
parser.advance()
code = Code()
parser = Parser(sys.argv[1])
parser.advance()
var_stack = 16
while parser.hasMoreCommands():
cmd_type = parser.commandType()
if cmd_type == 'A_COMMAND':
number = 32768
try:
addr = int(parser.symbol())
except:
if table.contains(parser.symbol()):
addr = table.getAddress(parser.symbol())
else:
table.addEntry(parser.symbol(), var_stack)
addr = var_stack
var_stack += 1
bin_number = bin(number | addr)[3:]
assembly = '0' + bin_number
print assembly
elif cmd_type == 'C_COMMAND':
assembly = '111'
assembly += code.comp(parser.comp())
assembly += code.dest(parser.dest())
assembly += code.jump(parser.jump())
print assembly
parser.advance()
The part to note is at the beginning lines 4-6 where it's checking the file name. So once I run my program I get 'need filename' printed to the screen and an error message that looks like this:
Traceback (most recent call last):
File "C:\Python27\Assembler.py", line 98, in <module>
sys.exit(-1)
SystemExit: -1
So where can I input the filename to avoid this error?
The way you have it, Python expects the filename as an argument:
python file.py your_file.asm
If you want to prompt for a filename, use raw_input() (or input() for Python 3):
filename = raw_input('Enter a filename: ') or 'default_file.asm'
sys.argv contains command line arguments.
So, this script has to be run through command-line, for getting input, as said by blender, use raw_input (or input) for getting input from the user, if there are not enough command-line arguments.
Something like this:
if len(sys.argv) == 1:
print "You can also give filename as a command line argument"
filename = raw_input("Enter Filename: ")
else:
filename = sys.argv[1]
And change the line
parser = Parser(sys.argv[1])
To
parser = Parser(filename)

do not understand this use of sys module

Here is code from a tutorial in A Byte of Python:
import sys
filename = 'poem.txt'
def readfile(filename):
#Print a file to standard output
f = file(filename)
while True:
line = f.readline()
if len(line) == 0:
break
print line,
f.close()
if len(sys.argv) < 2:
print 'No action specified'
sys.exit() //<--This is where the error is occurring
if sys.argv[1].startswith('--'):
option = sys.argv[1][2:] #fetches sys.argv[1] without first 2 char
if option == 'version':
print 'Version 1.2'
elif option == 'help':
print '''\
This program prints files to the standard output.
Any number of files can be specified.
Options include:
--version: Prints the version number
--help: Displays this help'''
else:
print 'Unknown option'
sys.exit()
else:
for filename in sys.argv[1:]:
readfile(filename)
When I run this code, this is the error that appears:
Traceback (most recent call last):
File "C:/Python/sysmodulepr.py", line 17, in <module>
sys.exit()
SystemExit
I don't understand why. Please help.
It's telling you that sys.exit() has executed on line 17 of your program.
The entry for for sys.exit in the Python documentation tells you that this exits your program.
There's no way this line can execute without producing other output, so I think there's something missing in the question.
If you're using IDLE, it will print the stack anyway. Try running your script from the command line, it won't print that error message when executed outside the IDE.
It's not an error. sys.exit() raises SystemExit exception to allow try:... finally block to cleanup used resources
Try in Idle:
import sys
sys.exit()
From documentation for sys.exit():
Exit from Python. This is implemented by raising the SystemExit exception, so cleanup actions specified by finally clauses of try statements are honored, and it is possible to intercept the exit attempt at an outer level.
edit
The error shouldn't be normally printed unless you're trying to run the script in some interactive interpreters (for example Idle).
It's nothing to worry about, but the script looks like it's standalone, so you should use it as such.

how to interact with an external script(program)

there is a script that expects keyboard input,
i can call that script with os.system('./script') in python,
how is it possible to send back an input to the script from another calling script?
update:
the script is:
$ cat script
#!/usr/bin/python
for i in range(4):
name=raw_input('enter your name')
print 'Welcome %s :) ' % name
when i try without a for loop, it works but it shows the output only when the script quits.
>>> p = subprocess.Popen('./script',stdin=subprocess.PIPE)
>>> p.communicate('navras')
enter your nameWelcome navras :)
when i try it with the foor loop, it throws error, How to display the statements interactive as and when the stdout is updated with new print statements
>>> p.communicate('megna')
enter your nameWelcome megna :)
enter your nameTraceback (most recent call last):
File "./script", line 3, in <module>
name=raw_input('enter your name')
EOFError: EOF when reading a line
(None, None)
You can use subprocess instead of os.system:
p = subprocess.Popen('./script',stdin=subprocess.PIPE)
p.communicate('command')
its not testet
In fact, os.system and os.popen are now deprecated and subprocess is the recommended way to handle all sub process interaction.

Categories

Resources