Pickling data in python - python

I have been staring at this code for a day and a half now and google is not helping. It looks fine to me but it keeps throwing out errors.
The program runs through a quiz and collects a score at the end as shown here:
print("That was the last question!")
print("Your final score is", score)
name = input('What is the players name? ')
highsc = highscore(score, name)
I Know that score works but when i enter the players name it then tries to run my highscore definition:
def highscore(score, name):
entry = (score, name)
hs_data = open('tops.dat', 'rb')
highsc = pickle.load(hs_data)
hs_data.close()
hs_data = open('tops.dat', 'ab')
highsc.append(entry)
highsc.sort(reverse=True)
highsc = highsc[:5]
pickle.dump(highsc, hs_data)
hs_data.close()
return highsc
But the i get the same error each time which is:-
File "C:\Users\Desktop\py3e_source\py3e_source\trivia_challenge.py", line 55, in highscore
highsc = pickle.load(hs_data)
File "C:\Python31\lib\pickle.py", line 1365, in load
encoding=encoding, errors=errors).load()
EOFError
Please help.

You are opening an empty file, pickle is reaching the end before it finds anything to unpickle. You can fix this by catching the EOFError and setting a default value when caught.
Something like this should work:
with open('tops.dat', 'rb') as hs_data:
try:
highsc = pickle.load(hs_data)
except EOFError:
highsc = []

The error says EOFError, which means you have reached the end of the file and pickle was not in a normal state. Is the file filled before using that function?
Also, opening the file in append mode to write the new data doesn't seem like a good idea. load reads the entire file, not discarding characters after the first object, but once you have added a new highscore, you have two highscore objects in the file, which also leads to an error.

Related

Python code isnt printing contents of txt?

elif menuOption == "2":
with open("Hotel.txt", "a+") as file:
print (file.read())
Ive tried many different ways but my python file just refuses to print the txt contents. It is writing to the file but option 2 wont read it.
if menuOption == "1":
print("Please Type Your Guests Name.")
data1 = (input() + "\n")
for i in range (2,1000):
file = open("hotel.txt", "a")
file.write(data1)
print("Please Write your Guests Room")
data2 = (input("\n") + "\n")
file.write(data2)
data3 = random.randint(1, 999999)
file.write(str (data3))
print("Guest Added - Enjoy Your Stay.")
print("Guest Name is:", data1)
print("Guest Room Number Is:", data2)
print("Your Key Code Is:", data3)
I want all the above information to be added to a TXT. (That works) and then be able to read it also. which won't work.
Why and how can I fix?
You have to use r instead of a+ to read from file:
with open("Hotel.txt", "r") as file:
You are using a+ mode which is meant for appending to the file, you need to use r for reading.
Secondly I notice this
for i in range (2,1000):
file = open("hotel.txt", "a")
You are opening a new file handler for every iteration of the loop. Please open the file just once and then do whatever operations you need to like below.
with open("hotel.txt", "a") as fh:
do your processing here...
This has the added advantage automatically closing the file handler for you, otherwise you need to close the file handler yourself by using fh.close() which you are not doing in your code.
Also a slight variation to how you are using input, you don't need to print the message explicitly, you can do this with input like this.
name = input("Enter your name: ")

Format path within Text File for consumption in Python

I am writing a Python script for use by multiple non-Python users.
I have a text file containing the parameters my script needs to run.
One of the inputs is a path. I cannot get my script to run and was thinking it was because I had referenced my path incorrectly.
I have tried:
C:\temp\test
"C:\temp\test"
r"C:\temp\test"
C:/temp/test
"C:/temp/test"
C:\\temp\\test
"C:\\temp\\test"
I have added each one of these into a text file, which is called and read in my Python script.
I have other parameters and they are called correctly, my script seems to run when I hard code the path in. I say seems because I think there are a few bugs I need to check, but it runs with no errors.
When I use the text file I get this error - which varies depending on if I used one of the above examples:
WindowsError: [Error 123] The filename, directory name, or volume
label syntax is incorrect: 'c:\temp\match1\jpg\n/.'
My code is as follows:
print ("Linking new attachments to feature")
fp = open(r"C:\temp\Match1\Match_Table.txt","r") #reads my text file with inputs
lines=fp.readlines()
InFeat = lines[1]
print (InFeat)
AttFolder = lines[3] #reads the folder from the text file
print (AttFolder)
OutTable = lines[5]
if arcpy.Exists(OutTable):
print("Table Exists")
arcpy.Delete_management(OutTable)
OutTable = lines[5]
print (OutTable)
LinkF = lines[7]
print (LinkF)
fp.close()
#adding from https://community.esri.com/thread/90280
if arcpy.Exists("in_memory\\matchtable"):
arcpy.Delete_management("in_memory\\matchtable")
print ("CK Done")
input = InFeat
inputField = "OBJECTID"
matchTable = arcpy.CreateTable_management("in_memory", "matchtable")
matchField = "MatchID"
pathField = "Filename"
print ("Table Created")
arcpy.AddField_management(matchTable, matchField, "TEXT")
arcpy.AddField_management(matchTable, pathField, "TEXT")
picFolder = r"C:\temp\match1\JPG" #hard coded in
print (picFolder)
print ("Fields added")
fields = ["MatchID", "Filename"]
cursor = arcpy.da.InsertCursor(matchTable, fields)
##go thru the picFolder of .png images to attach
for file in os.listdir(picFolder):
if str(file).find(".jpg") > -1:
pos = int(str(file).find("."))
newfile = str(file)[0:pos]
cursor.insertRow((newfile, file))
del cursor
arcpy.AddAttachments_management(input, inputField, matchTable, matchField, pathField, picFolder)
From your error "'c:\temp\match1\jpg\n/.'", i can see "\n" character, \n is symbole of new line ( when you press enter button ) you should remove that character from end of your path! did you try to do that? you can use .lstrip("\n") , replcae() or regx methods for remove that character.
Try to open and read line by line of your input file like this:
read_lines = [line.rstrip('\n') for line in open(r"C:\temp\Match1\Match_Table.txt")]
print(read_lines)
print(read_lines[1])

Try/Except Block causing ValueError

for my coding assignment I am to create a file that will read a csv file, offer different attributes to do analysis over (determined by the column values. I had this code working perfectly, but after I added my first try/except block I started getting the following error:
Traceback (most recent call last): File
"/Users/annerussell/Dropbox/Infotec 1040/module 8/csval.py", line 49,
in
row1=next(reader, 'end')[0:] ValueError: I/O operation on closed file.
Here is a link to a file you can test it with if desired. As you probably guessed this is a class assignment, and I am working on learning python for gradschool anyway so any suggestions are greatly appreciated.
import csv
print('Welcome to CSV Analytics!')
# Get file name and open the file
while True:
try:
file_name = input('Enter the name of the file you would like to process: ')
with open(file_name, "rt") as infile:
# Select the attribute to be analyzed
reader=csv.reader(infile)
headers=next(reader)[0:]
max=len(headers)
except FileNotFoundError:
print('The file you entered could not be found. Please' \
+ ' enter a valid file name, ending in .csv.')
continue
except IOError:
print('The file you selected could not be opened. Please ' \
+ 'enter a valid file name, ending in .csv.')
continue
except:
print('There was an error opening or reading your file. Please ' \
+ 'enter a valid file name, ending in .csv.')
continue
else:
print ('The attributes available to analyse are:')
for col in range(1, max):
print(col, headers[col])
while True:
try:
choice=int(input('Please select the number of the attribute you would like to analyze '))
except:
print('Please enter the numeric value for the selection you choose.')
continue
else:
# Build a dictionary with the requested data
dict1= {}
numrows=-1
row1=[]
largest_value=0
key_of_largest_value=0
while row1 != 'end':
row1=next(reader, 'end')[0:]
if row1 !='end':
numrows += 1
key=row1[0]
value=float(row1[choice])
dict1[key] = value
if value>largest_value:
largest_value=value
key_of_largest_value=key
# print('dictionary entry ( key, value)', key, value)
print('Largest ', headers[choice], ' value is ', key_of_largest_value, ' with ', largest_value)
In short: After with block ends, file is closed. You can't read from it, reader will fail.
Probably you didn't notice there is one-space indent for with, replace it with common indent so it will be more clear.
Seach for python context manager for more deep understanding.
Suggestion here is to factor out all logic from try else block to process_file function, and call it inside with statement.
with open(file_name, "rt") as infile:
# Select the attribute to be analyzed
reader=csv.reader(infile)
headers=next(reader)[0:]
max=len(headers)
process_file(reader, headers, max) # <-- like that
using with you need to move second condition to it block or
replace
with open(file_name, "rt") as infile:
with
isProcessing = True
while isProcessing:
....
infile = open(file_name, "rt")
...
#end of line
#print('Largest ',....
infile.close()
# end the loop
isProcessing = False

Cannot read Excel chart properly with intended line of code

So this might be a simple solution but I can't seem to come up with it. When I use the following code I can open the file, read through it and do all the necessary functions, but if I use the commented line instead of the one underneath it gives me an error at line r = L[15] like it can't read it properly anymore. What can I do about this? If more code is needed I can provide it. Thanks!
def open_file():
while True:
file = input("Enter a file name: ")
try:
open(file)
return file
except FileNotFoundError:
print("Error. Please try again.")
print()
def read_file():
#fp = open_file()
fp = open("Texas_death_row.csv")
csv_fp = csv.reader(fp)
data = []
for L in csv_fp:
r = L[15]
g = L[16]
v = L[27]
T = (r,g,v)
my_list.append(T)
return data
Your open_file function is returning the variable file, that contains the string containing the filename, not the file object (file descriptor) which is what you can read and whatnot.
You should try something like this:
def open_file():
while True:
file = input("Enter a file name: ")
try:
f = open(file)
return f # Return the "file object", not the file name
except FileNotFoundError:
print("Error. Please try again.")
print()
PS: When you're dealing with files, don't forget to close them when you're done with them.

how to append in a specific line in file in python 3?

I am making a program for my computer science assignment. I need to make a quiz for 3 classes in a primary school. Then the results have to be saved in a file. I've done the program till here but the next task asks me to let each student have 3 turns and give an average for each one.
here is the code I used to save the results into a text file:
def savetofile():
result = result ="\n "+ namestudent.get() + " "fscore.get()+"/4"
messagebox.showinfo("results", "your results been saved successfuly")
if int(year.get())==1:
f = open('results C1.txt', 'a')
f.write(result)
f.close()
if int(year.get())==2:
f = open('results C2.txt', 'a')
f.write(result)
f.close()
if int(year.get())==3:
f = open('results C3.txt', 'a')
f.write(result)
f.close()
how can I check if the new user taking the quiz has already done the quiz or not and how can I add the new results of that person in front of their name also how can I take the average of their 3 sets of score.
first of all, you output your results been saved successfully before writing to a file, which is not true, because the file writing can fail and thus not end up done successfully.
Then you do open and close your file in the following way:
f = open('results C1.txt', 'a')
f.write(result)
f.close()
which is wrong as well because if the write fails for any reason (like an exception reading the result variable), the file won't be closed properly, and the output may not get flushed to it.
You should instead do:
with open('results C1.txt', 'a') as f:
f.write(result)
which will take care of opening, flushing and closing the file correctly.
Then the following line is wrong:
result = result ="\n "+ namestudent.get() + " "fscore.get()+"/4"
as it misses a + between the spaces and the score result. You'd better write something like (with the \n at the end to avoid having an empty first line):
result = "{} {}/4\n".format(namestudent.get(), fscore.get())
how can I check if the new user taking the quiz has already done the quiz or not?
To do it you need to do the following algorithm:
# to open the file:
with open('results C1.txt', 'r') as results:
# read the file
for result in results:
# split the line
name, score = result.split(" ")
if name == namestudent.get():
# do something when the student exists
how can I add the new results of that person in front of their name also how can I take the average of their 3 sets of score?
Then my suggestion for this is to not work directly with the files, but instead open up a "cache" dictionary of all the scores:
def load_scores():
years_tuple_default = (None, None, None) # create a tuple with as many entries as there can be years
student_scores = dict()
with open('results C1.txt', 'r') as results:
# read the file
for result in results:
# split the line
name, score = result.split(" ")
student_scores.setdefault(name, years_tuple_default)[0] = score
with open('results C2.txt', 'r') as results:
# read the file
for result in results:
# split the line
name, score = result.split(" ")
student_scores.setdefault(name, years_tuple_default)[1] = score
with open('results C3.txt', 'r') as results:
# read the file
for result in results:
# split the line
name, score = result.split(" ")
student_scores.setdefault(name, years_tuple_default)[2] = score
return student_scores
Then, create a function save the cache into the files:
def save_scores(student_scores):
with open('results C1.txt', 'w') as results_y1:
with open('results C2.txt', 'w') as results_y2:
with open('results C3.txt', 'w') as results_y3:
for student, scores in student_scores:
results_y1.write("{} {}/4\n".format(student, scores[0]))
results_y2.write("{} {}/4\n".format(student, scores[1]))
results_y3.write("{} {}/4\n".format(student, scores[2]))
print("Results saved!")
And finally, work against that cache:
def update_scores(student_scores, namestudent, fscore, year):
if namestudent.get() not in student_scores.keys():
# add the student entry
student_scores.setdefault(namestudent.get(), (None, None, None))[int(year.get())-1] = fscore.get()
else:
# update the student year entry
student_scores[int(year.get())-1] = fscore.get()
which would end up with a code looking like that to put it all together:
student_scores = load_scores()
# do your stuff to get the namestudent/fscore/year data
update_scores(student_scores, namestudent, fscore, year)
# when all updates are done, you can alter the files
save_scores(student_scores)
To sum up:
split your algorithm into functions,
protect your file handling using the with statement
read the files once to create a "cache" to work against, and save the result at once when you're done
Bonus ideas
use a class
From there, to get further, you could create a class, and have all that as methods:
class StudentScores:
def __init__(self):
self._student_scores = dict()
def load_scores(self):
# TODO
def save_scores(self):
# TODO
def update_score(self):
# TODO
And then calculating the mean of the scores is simple stupid, it's just adding a method to the class which prototype would look like:
class StudentScores:
…
def get_mean_scores(self, student):
score_y1, score_y2, score_y3 = self._student_scores[student]
score = # calculate the average of the three score
return score
use a with statement
And if you want to shine, you could implement it as working with the with statement:
class StudentScores:
def __init__(self):
self._student_scores = dict()
def load_scores(self):
# TODO
def save_scores(self):
# TODO
def update_score(self):
# TODO
def __enter__(self):
self.load_scores()
return self
def __exit__(self, type, value, traceback):
self.save_scores()
And then your code would like that:
with StudentScores() as student_scores:
# do your stuff to get the namestudent/fscore/year data
update_scores(student_scores, namestudent, fscore, year)
To conclude, I'm showing you how I'd design something to do your assignment, whereas I'm not trying to do your assignment on your behalf. My goal here is to help you get ideas and learn something about software design and python. Some things may be above your current level (like how to create a with statement), but as you're learning, you'll be able to fully understand and apply everything I'm telling you here.
HTH

Categories

Resources