Python for absolute beginners chapter 7 challenge 2 - python

I am currently working through the python for absolute beginners 3rd addition. I am struggling with the 2nd challenge in the 7th chapter of the book, as i keep getting an error i don't understand.
The challenge is to:
"improve triva challenge game so that it maintains a high score list in a file. The program should records the player's name and score if the player makes the list. store the high scores using a pickled object."
The original code
# Trivia Challenge
# Trivia game that reads a plain text file
import sys
def open_file(file_name, mode):
"""Open a file."""
try:
the_file = open(file_name, mode)
except IOError as e:
print("Unable to open the file", file_name, "Ending program.\n", e)
input("\n\nPress the enter key to exit.")
sys.exit()
else:
return the_file
def next_line(the_file):
"""Return next line from the trivia file, formatted."""
line = the_file.readline()
line = line.replace("/", "\n")
return line
def next_block(the_file):
"""Return the next block of data from the trivia file."""
category = next_line(the_file)
question = next_line(the_file)
answers = []
for i in range(4):
answers.append(next_line(the_file))
correct = next_line(the_file)
if correct:
correct = correct[0]
explanation = next_line(the_file)
return category, question, answers, correct, explanation
def welcome(title):
"""Welcome the player and get his/her name."""
print("\t\tWelcome to Trivia Challenge!\n")
print("\t\t", title, "\n")
def main():
trivia_file = open_file("trivia.txt", "r")
title = next_line(trivia_file)
welcome(title)
score = 0
# get first block
category, question, answers, correct, explanation = next_block(trivia_file)
while category:
# ask a question
print(category)
print(question)
for i in range(4):
print("\t", i + 1, "-", answers[i])
# get answer
answer = input("What's your answer?: ")
# check answer
if answer == correct:
print("\nRight!", end=" ")
score += 1
else:
print("\nWrong.", end=" ")
print(explanation)
print("Score:", score, "\n\n")
# get next block
category, question, answers, correct, explanation = next_block(trivia_file)
trivia_file.close()
print("That was the last question!")
print("You're final score is", score)
main()
input("\n\nPress the enter key to exit.")
my attempt at the challenge code
# Trivia Challenge
# Trivia game that reads a plain text file
import sys, pickle
def open_file(file_name, mode):
"""Open a file."""
try:
the_file = open(file_name, mode)
except IOError as e:
print("Unable to open the file", file_name, "Ending program.\n", e)
input("\n\nPress the enter key to exit.")
sys.exit()
else:
return the_file
def next_line(the_file):
"""Return next line from the trivia file, formatted."""
line = the_file.readline()
line = line.replace("/", "\n")
return line
def next_block(the_file):
"""Return the next block of data from the trivia file."""
category = next_line(the_file)
points = next_line(the_file)
question = next_line(the_file)
answers = []
for i in range(4):
answers.append(next_line(the_file))
correct = next_line(the_file)
if correct:
correct = correct[0]
explanation = next_line(the_file)
return category, points, question, answers, correct, explanation
def welcome(title):
"""Welcome the player and get his/her name."""
print("\t\tWelcome to Trivia Challenge!\n")
print("\t\t", title, "\n")
def high_scores():
global score
value = int(score)
name = input("What is your name? ")
entry = (value, name)
f = open("high_scores.dat", "wb+")
high_scores = pickle.load(f)
high_scores.append(entry)
high_scores = high_scores[:5]
print("High Scores\n")
print("NAME\tSCORE")
for entry in high_scores:
value, name = entry
print(name, "\t", value)
pickle.dump(high_scores, f)
f.close()
def main():
trivia_file = open_file("trivia.txt", "r")
title = next_line(trivia_file)
welcome(title)
# get first block
category, points, question, answers, correct, explanation = next_block(trivia_file)
while category:
# ask a question
print(category)
print(question)
for i in range(4):
print("\t", i + 1, "-", answers[i])
# get answer
answer = input("What's your answer?: ")
# check answer
if answer == correct:
print("\nRight!", end=" ")
j = int(points)
global score
score += j
else:
print("\nWrong.", end=" ")
print(explanation)
print("Score:", score, "\n\n")
# get next block
category, points, question, answers, correct, explanation = next_block(trivia_file)
trivia_file.close()
print("That was the last question!")
print("You're final score is", score)
high_scores()
score = 0
main()
input("\n\nPress the enter key to exit.")
And the wonderfully confusing error
Traceback (most recent call last):
File "C:\Users\Cheyne\Desktop\Python\chapter07\Challenges\temp.py", line 104, in <module>
main()
File "C:\Users\Cheyne\Desktop\Python\chapter07\Challenges\temp.py", line 100, in main
high_scores()
File "C:\Users\Cheyne\Desktop\Python\chapter07\Challenges\temp.py", line 54, in high_scores
high_scores = pickle.load(f)
File "C:\Python31\lib\pickle.py", line 1365, in load
encoding=encoding, errors=errors).load()
EOFError
Can anyone help explain what's going wrong here please? I have been staring at it for days.

You have an "EOFError", which is an "End Of File Error" at line 54.
That's where you try to load the pickle file so, considering that you are not checking that the file actually exists, my guess is that you have no file and get the error.
Either create an initial file by yourself, or check that it exists and is valid before trying to load it.
EDIT: I just noticed that you open the pickle file as "wb+", which means that you open it for writing and try to read it. You're overwriting the file, which becomes zero bytes. If you want to append to the existing file, you should use "a" instead of "w". Again, before loading make sure the file contains valid data.

Related

python trivia game error

Trying to have a game where each question has a unique value associated to it. The player's score is then the total number of points of the questions she or he answers correctly. Been fiddling with it but I keep running into these errors :
code:
# Trivia Challenge
# Trivia game that reads a plain text file
import sys
def open_file(file_name, mode):
"""Open a file."""
try:
the_file = open(file_name, mode)
except IOError as e:
print("Unable to open the file", file_name, "Ending program.\n", e)
input("\n\nPress the enter key to exit.")
sys.exit()
else:
return the_file
def next_line(the_file):
"""Return next line from the trivia file, formatted."""
line = the_file.readline()
line = line.replace("/", "\n")
return line
def next_block(the_file):
"""Return the next block of data from the trivia file."""
category = next_line(the_file)
point_value = 0
question = next_line(the_file)
answers = []
answers.append(next_line(the_file))
if( answers[0]=="True\n"):
answers.append(next_line(the_file))
else:
for i in range(4):
answers.append(next_line(the_file))
correct = next_line(the_file)
if correct:
correct = correct[0]
point_value = (int)(next_line(the_file).strip())
explanation = next_line(the_file)
return category, question, answers, correct, explanation, point_value
def welcome(title):
"""Welcome the player and get his/her name."""
print("\t\tWelcome to Trivia Challenge!\n")
print("\t\t", title, "\n")
def main():
trivia_file = open_file("trivia.txt", "r")
title = next_line(trivia_file)
welcome(title)
score = 0
# get first block
category, question, answers, correct, explanation, point_value = next_block(trivia_file)
while category:
# ask a question
print(category)
print(question)
i=0
for a in answers:
print ("\t", i + 1, "-", a)
i = i + 1 # get answer
answer = input("What's your answer?: ")
# check answer
if answer == correct:
print("\nRight!", end=" ")
score += 1
else:
print("\nWrong.", end=" ")
print(explanation)
print("Score:", score, "\n\n")
# get next block
category, question, answers, correct, explanation, score, point_value = next_block(trivia_file)
trivia_file.close()
print("That was the last question!")
print("You're final score is", score)
main()
input("\n\nPress the enter key to exit.")
not sure why it's having these errors/why its not running - suggestions? ty!
this is connected to a seperate .txt file named "trivia.txt" with all the questions and points.
Most likely the error is occurring because your text file contains unicode characters. You can add the encoding parameter to the open call to tell python that it isn't in the default ascii encoding.
the_file = open(file_name, mode, encoding='utf-8')
If this doesn't work, it may be because the file is using a different encoding such as 'iso-8859-15'.
The Python documentation Unicode-HOWTO has more details about dealing with Reading and Writing Unicode Data.

Michael Dawson's trivia game assignment

Please help me to understand what I'm doing wrong.
I'm getting error
NameError: name 'name' is not defined
Regardless function welcome returns name.
Here's the code.
import sys, pickle, shelve
def open_file(file_name, mode):
"""Open a file."""
try:
the_file = open(file_name, mode)
except IOError as e:
print("Unable to open the file", file_name, "Ending program.\n", e)
input("\n\nPress the enter key to exit.")
sys.exit()
else:
return the_file
def next_line(the_file):
"""Return next line from the trivia file, formatted."""
line = the_file.readline()
line = line.replace("/", "\n")
return line
def next_block(the_file):
"""Return the next block of data from the trivia file."""
category = next_line(the_file)
question = next_line(the_file)
answers = []
for i in range(4):
answers.append(next_line(the_file))
correct = next_line(the_file)
if correct:
correct = correct[0]
score = next_line(the_file)
explanation = next_line(the_file)
return category, question, answers, correct, score, explanation
def welcome(title):
"""Welcome the player and get his/her name."""
print("\t\tWelcome to Trivia Challenge!\n")
print("\t\t", title, "\n")
name = input('Enter your name')
return name
def pic_save(name, final_score):
records = {name: final_score}
f = open('pickles.dat', 'ab')
pickle.dump(records, f)
return records
def pic_read():
f = open("pickles.dat", "rb")
records = pickle.load(f)
print(records)
f.close()
def main():
trivia_file = open_file("7.1.txt", "r")
title = next_line(trivia_file)
welcome(title)
final_score = 0
# get first block
category, question, answers, correct, score, explanation = next_block(trivia_file)
while category:
# ask a question
print(category)
print(question)
for i in range(4):
print("\t", i + 1, "-", answers[i])
# get answer
answer = input("What's your answer?: ")
# check answer
if answer == correct:
print("\nRight!", end=" ")
final_score += int(score)
print("Score:", score, "\n\n")
else:
print("\nWrong.", end=" ")
print(explanation)
# get next block
category, question, answers, correct, score, explanation = next_block(trivia_file)
trivia_file.close()
pic_save(name, final_score)
print("That was the last question!")
print("You're final score is", final_score)
pic_read()
main()
input("\n\nPress the enter key to exit.")
Probably what you want to do is assign the return value of welcome to a variable named name, otherwise the return value is lost.
name = welcome(title)

Golf scores python program

I am trying to create two programs one that writes the data to file golf.txt and the second which reads the records from golf.txt and displays them. The first program I am trying to get the program to quit when you leave the input field blank. Here's my code for the first program.
#Program that reads each player's name and golf score as input
#Save to golf.txt
outfile = open('golf.txt', 'w')
#Enter input, leave blank to quit program
while True:
name = input("Player's name(leave blank to quit):")
score = input("Player's score(leave blank to quit):")
if input ==" ":
break
#write to file golf.txt
outfile.write(name + "\n")
outfile.write(str(score) + "\n")
outfile.close()
With the second program I can't get the program to display the output I want on one line. Here's the second program.
#Golf Scores
# main module/function
def main():
# opens the "golf.txt" file created in the Golf Player Input python
# in read-only mode
infile = open('golf.txt', 'r')
# reads the player array from the file
player = infile.read()
# reads the score array from the file
score = infile.read()
# prints the names and scores
print(player + "scored a" + score)
# closes the file
infile.close()
# calls main function
main()
Any help or suggestions I can get would be greatly appreciated.
Two main problems:
1.) you first code has if input == ' ' which is wrong in two ways:
input is a function. you already saved the input so you should be comparing with name and score.
input returns a '' when you dont input anything, not a ' '.
so change to: if name == '' or score == '': or even if '' in (name,score): (does the same things)
2.) file.read() will automatically read EVERYTHING in the file as one string. You want to split it into each component so you can either do something like:
player,score = file.readlines()[:2]
or
player = file.readline()
score = file.readline()
then print (with leading and trailing spaces in your middle string!)
print(player + " scored a " + score)
Got both programs working
program 1:
#Program that reads each player's name and golf score as input
#Save to golf.txt
outfile = open('golf.txt', 'w')
#Enter input, leave blank to quit program
while True:
name = input("Player's name(leave blank to quit):")
if name == "":
break
score = input("Player's score:")
#write to file golf.txt
outfile.write(name + "\n")
outfile.write(str(score) + "\n")
outfile.close()
program 2:
#Golf Scores
# main module/function
def main():
# opens the "golf.txt" file created in the Golf Player Input python
# in read-only mode
infile = open('golf.txt', 'r')
# reads the player array from the file
name = infile.readline()
while name != '':
# reads the score array from the file
score = infile.readline()
# strip newline from field
name = name.rstrip('\n')
score = score.rstrip('\n')
# prints the names and scores
print(name + " scored a " + score)
# read the name field of next record
name = infile.readline()
# closes the file
infile.close()
# calls main function
main()
Eliminate spaces from the input before checking (I would use .strip() method). And compare it to the empty string "" instead of space(s) " ".
With the "while true" block you keep asking and taking the names and the scores, but you overwrite them so you always will have just the last pair.
You need to keep them all, so you can make a list:
names_and_scores = []
while True:
name = input("Player's name(leave blank to quit):").strip()
if name == "":
break
score = input("Player's score:").strip()
if name != "" and score != "":
names_and_scores.append("{}; {}".format(name, score))
with open('golf.txt', 'w') as outfile:
outfile.write("\n".join(names_and_scores))
The second program opens the file, read lines one by one, splits them and print:
with open('golf.txt', 'r') as infile:
for line in infile:
name, score = line.strip().split("; ")
print("{} scored a {}.".format(name, score))

Pickle in Python

How do you save and load a variable using pickle? I am trying to save and load a high score from a trivia game. Here is the relevant code:
high_scorz=open_file("high.dat", "wb+")
high = 0
try:
high=pickle.load(high_scorz)
except EOFError:
print("EOF ERROR!!!!")
finally:
print("NO DATA RECEIVED")
# later in the code when score has been updated
if score > high:
pickle.dump(score, high_scorz)
high = score
trivia_file.close()
high_scorz.close()
print("High Scorz: " + str(high))
The problem is every time score and high are equal. high = 0 every time because every time I receive a end of file error. Therefor when I run the final print statement it always prints the current score.
Heres all of the code if you want it:
# Trivia Challenge
# Trivia game that reads a plain text file
import pickle
import sys
def open_file(file_name, mode):
"""Open a file."""
try:
the_file = open(file_name, mode)
except IOError as e:
print("Unable to open the file", file_name, "Ending program.\n", e)
input("\n\nPress the enter key to exit.")
sys.exit()
else:
return the_file
def next_line(the_file):
"""Return next line from the trivia file, formatted."""
line = the_file.readline()
line = line.replace("/", "\n")
return line
def next_block(the_file):
"""Return the next block of data from the trivia file."""
category = next_line(the_file)
question = next_line(the_file)
answers = []
for i in range(4):
answers.append(next_line(the_file))
correct = next_line(the_file)
if correct:
correct = correct[0]
points = next_line(the_file)
explanation = next_line(the_file)
return category, question, answers, correct, points, explanation
def welcome(title):
"""Welcome the player and get his/her name."""
print("\t\tWelcome to Trivia Challenge!\n")
print("\t\t", title, "\n")
def main():
trivia_file = open_file("trivia.txt", "r")
high_scorz=open_file("high.dat", "wb+")
high = 0
try:
high=pickle.load(high_scorz)
except EOFError:
print("EOF ERROR!!!!")
finally:
print("NO DATA RECEIVED")
title = next_line(trivia_file)
welcome(title)
score = 0
# get first block
category, question, answers, correct, points, explanation = next_block(trivia_file)
while category:
# ask a question
print(category)
print(question)
for i in range(4):
print("\t", i + 1, "-", answers[i])
# get answer
answer = input("What's your answer?: ")
# check answer
if answer == correct:
print("\nRight!", end=" ")
score += int(points)
else:
print("\nWrong.", end=" ")
print(explanation)
print("Score:", score, "\n\n")
# get next block
category, question, answers, correct, points, explanation = next_block(trivia_file)
print("That was the last question!")
print("You're final score is", score)
if score > high:
pickle.dump(score, high_scorz)
high = score
trivia_file.close()
high_scorz.close()
print("High Scorz: " + str(high))
main()
input("\n\nPress the enter key to exit.")
If you open with a w mode, you overwrite any previous data. It would be easier to open the file twice:
filename = "high.dat"
with open(filename) as high_scores:
try:
high_score = pickle.load(high_scores)
except Exception:
print("No data loaded")
high_score = 0
# later in the code when score has been updated
if score > high_score:
with open(filename, 'w') as high_scores:
pickle.dump(score, high_scores)
high_score = score

python unboundLocalError why

import os
def createFile():
if os.path.exists("highscores.txt") == False:
myFile = open("highscores.txt","w")
myFile.close()
def inputInt():
number = input(str("please input your score "))
try:
return int(number)
except:
print ("this is not an acceptable input, please try again")
inputInt()
def addScore():
name = input("Please enter the name you wish to add")
score = inputInt()
messages = "thank you"
'''open the highscores line and read in all the lines to a list called scorelist.
then close the file'''
scoresFile = open("highscores.txt","r")
scoresList = scoresFile.readlines()
scoresFile.close()
#check each line in the scoresList list
for i in range(0,len(scoresList) ):
#check to see if the name is in the line
if name in scoresList[i]:
#if it is then strip the name from the text. this should leave theb score
tempscore = scoresList[i].replace(name,"")
#if the score is higher then add it to the list
if int(tempscore)<score:
message = "Score updated"
scoresList[i] = (name + str(score))
#write the scores back to the file
scoresFile = open("highscores.txt","w")
for line in scoresList:
scoresFile.write(line + "\n")
scoresFile.close()
#no need to continue so break
break
else:
#message as score too low
message= "score too low. not updated"
if message("Score updated"):
message = "New score added"
scoresFile = open("highscores.txt","a")
scoresFile.write(name + str(score) + "\n")
scoresFile.close()
print (message)
addScore()
Above is the code. The error shown is:
Traceback (most recent call last):
File "E:\Computer Science\python code\highScores\highscores1.py", line 66, in <module>
addScore()
File "E:\Computer Science\python code\highScores\highscores1.py", line 60, in addScore
File "E:\Computer Science\python code\highScores\highscores1.py", line 60, in addScore
if message("Score updated"):
UnboundLocalError: local variable 'message' referenced before assignment
(1) You are referring to message which is undefined when no names are found in scoresList[i]. Put a
message = ""
line before your for loop. I don't know your actual intent, so this will make the error go away but check if the logic is still correct.
(2) You are doing the comparison incorrectly. You should write
if message == "Score updated":
instead of
if message("Score updated"):

Categories