Pickle high scores and then print - python

I'm trying to pickle high scores and then print them.
In the actual program, score is acquired from a simple trivia game.
score = 10
name = input("Name: ")
scores = [name, score]
high_scores = open("high_scores.dat", "ab")
pickle.dump(scores, high_scores)
high_scores.close()
high_scoresR = open("high_scores.dat", "rb")
results = pickle.load(high_scoresR)
print(results)
high_scores.close()
The program prints only the first high score entered, it doesn't matter how many scores I try to dump to it. Example:
['Jason', 10]
I am guessing I don't understand something quite basic, so I would highly appreciate a informative and clear explanation.

You can use 'wb' mode to write multiple pickles to a file, and if you need to reopen it for one ore more additional dump, then you should use append mode ('a', not 'w'). Here I write multiple entries using 'wb', and then later add one entry using 'ab'.
>>> scores = dict(Travis=100, Polly=125, Guido=69)
>>> import pickle
>>> with open('scores.pkl', 'wb') as highscores:
... for name,score in scores.items():
... pickle.dump((name,score)), highscores)
...
>>> with open('scores.pkl', 'ab') as highscores:
... pickle.dump(scores, highscores)
...
>>> with open('scores.pkl', 'rb') as highscores:
... a = pickle.load(highscores)
... b = pickle.load(highscores)
... c = pickle.load(highscores)
... d = pickle.load(highscores)
...
>>> a
('Travis', 100)
>>> b
('Polly', 125)
>>> c
('Guido', 69)
>>> d
{'Polly': 125, 'Travis': 100, 'Guido': 69}
>>>
And if you have a lot of data, so that you are worried about being able to dump and/or load all of your items at once, then you can use (one of my packages) klepto, which enables you to store large pickled data to a file, directory, or database… where you can seamlessly access one entry at a time.
>>> import klepto
>>> store = klepto.archives.dir_archive('high', serialized=True)
>>> store.update(scores)
>>> store
dir_archive('high', {'Polly': 125, 'Guido': 69, 'Travis': 100}, cached=True)
>>> # dump all entries at once
>>> store.dump()
>>> # create a new empty archive proxy
>>> store2 = klepto.archives.dir_archive('high', serialized=True)
>>> store2
dir_archive('high', {}, cached=True)
>>> # load one entry, as opposed to loading all entries
>>> store2.load('Guido')
>>> store2
dir_archive('high', {'Guido': 69}, cached=True)
>>> store2['Guido']
69
>>> # load everything else
>>> store2.load()
>>> store2
dir_archive('high', {'Polly': 125, 'Guido': 69, 'Travis': 100}, cached=True)
>>>

You could read your file into a dictionary:
name = input('Enter name: ')
score = input('Enter score: ')
# write new entry to file
with open('highscores.txt', 'a') as f:
f.write(name + ':' + score + '\n')
# read file into dict
with open('highscores.txt', 'r') as f:
lines = f.read().splitlines()
scores = dict(line.split(':') for line in lines)
for key, value in scores.items():
print(key, value)
I didn't know you were trying to learn pickle, but maybe this helps someone else.

Related

Does anyone know how to get info from a csv?

Im trying to collect info from a csv file and turn the row values into variables and carry those variables into different def functions finding such variables such as the max of whats inside and basically gather information from the csv.
Simple, you can use the csv module
for example, have the following csv file
a,1
b,7
c,5
d,2
e,6
>>> import csv
>>> filename = "/Users/sunnky/Desktop/test.csv"
>>> d = {}
>>> with open(filename, mode='r', encoding='utf-8-sig') as f:
... reader = csv.reader(f)
... for k, v in reader:
... d[k] = v
...
>>> new_d = sorted(d.items(), key = lambda m: m[1])
>>> min, max = new_d[0], new_d[len(new_d)-1]
>>> print(min, max)
('a', '1') ('b', '7')

Updating dictionary values of keys from a .txt file

So I've created a dictionary off the txt file "PM.txt" where the key is the player and the value is their penalty minutes. I know dictionary keys have to be unique so how would I update the value of the key adding it to the current value, as the key exists more than once in the txt file.
"PM.txt"
Neil,2
Paul,5
Neil,10
Santos,2
Neil,2
Santos,10
Paul,2
Alex,2
So far I have this which returns:
{'Alex': 2, 'Santos': 10, 'Paul': 2, 'Neil': 2}
def pm_dict(filename):
f = open(filename, 'r')
dict = {}
for line in f:
x = line.split(",")
player = x[0]
minutes = x[1]
c = len(minutes)-2
minutes = minutes[0:c]
dict[player] = minutes
return dict
But how would I create a function or a helper for it to return:
{'Alex': 2, 'Santos': 12, 'Paul': 7, 'Neil': 14}
A couple of standard libraries make this problem straightforward. A defaultdict creates a key if it doesn't already exist of its default type, so you can use D[key] += value even when the key doesn't exist yet. The csv module automatically parses .csv files. the default separator is comma. Also make sure not to use dict as a variable name. It overwrites the dict type.
from collections import defaultdict
import csv
def pm_dict(filename):
D = defaultdict(int)
with open(filename, 'r', newline='') as f:
r = csv.reader(f)
for key,value in r:
D[key] += int(value)
return dict(D) # converts back to a standard dict, but not required.
print(pm_dict('PM.txt'))
Output:
{'Neil': 14, 'Paul': 7, 'Alex': 2, 'Santos': 12}
The values make more sense as numbers, but if you want value strings as in your example the last line of the function can be the following to convert values back to strings. This is a dictionary comprehension.
return {k:str(v) for k,v in D.items()}
First convert your minute to int:
minutes = int(x[1])
Then you add it to your dictionary:
if player in dict:
dict[player] += minutes
else:
dict[player] = minutes
in your for loop, instead of dict[player] = minutes:
if player not in dict:
dict[player] = 0
dict[player] += minutes
Also, instead of:
minutes = x[1]
c = len(minutes)-2
minutes = minutes[0:c]
You can do:
minutes = x[1].strip()
Just use defaultdict:
def pm_dict(filename):
f = open(filename, 'r')
dict = defaultdict(int)
for line in f:
x = line.split(",")
player = x[0]
minutes = x[1]
c = len(minutes)-2
minutes = minutes[0:c]
dict[player] += int(minutes)
return dict
After refactoring:
import csv
from collections import defaultdict
...
def get_penalty_minutes_dict(filename):
result_dict = defaultdict(int)
with open(filename, 'r') as f:
for player, minutes in csv.reader(f):
result_dict[player] += int(minutes)
return result_dict

Words, sorted by frequency, in a book (.txt file)

I'm using:
from collections import Counter
wordlist = open('mybook.txt','r').read().split()
c = Counter(wordlist)
print c
# result :
# Counter({'the': 9530, 'to': 5004, 'a': 4203, 'and': 4202, 'was': 4197, 'of': 3912, 'I': 2852, 'that': 2574, ... })
to print all the words of a book, sorted by frequency.
How to write this result in a .txt output file ?
g = open('wordfreq.txt','w')
g.write(c) # here it fails
Here is the desired output wordfreq.txt :
the, 9530
to, 5004
a, 5004
and, 4203
was, 4197
...
if you want to write it in a sorted manner you can do this.
from collections import Counter
wordlist = open('so.py', 'r').read().split()
word_counts = Counter(wordlist)
write_file = open('wordfreq.txt', 'w')
for w, c in sorted(word_counts.iteritems(), key=lambda x: x[1], reverse=True):
write_file.write('{w}, {c}\n'.format(w=w, c=c))
I think this may be the help you need: how to print the dictionary in the format you requested. The first four lines are your original code.
from collections import Counter
wordlist = open('so.py', 'r').read().split()
c = Counter(wordlist)
print c
outfile = open('output.txt', 'w')
for word, count in c.items():
outline = word + ',' + str(count) + '\n'
outfile.write(outline)
I think this can be done a little more simply. Also I used a context manager (with) to automatically close the files
from collections import Counter
with open('mybook.txt', 'r') as mybook:
wordcounts = Counter(mybook.read().split())
with open('wordfreq.txt', 'w') as write_file:
for item in word_counts.most_common():
print('{}, {}'.format(*item), file=write_file)
If the file is particularly large, you can avoid reading it all into memory at once by using
wordcounts = Counter(x for line in mybook for x in line.split())

itrate on a dictionary from a list with dictionary name

i am trying to iterate on a list were the variables in the list are dictionary names and then iterate on the keys in these dictionary
my code is like this :
IA = {"V":"CVolt","T":"CTemp"}
CLR = {"V":"CLR_Volt","T":"CLR_Temp"}
GT = {"V":"GT_CVolt","T":"GT_Temp"}
PP = ["IA","GT","CLR"]
AFT = {"IA":0,"GT":0,"CLR":0}
AFV = {"IA":0,"GT":0,"CLR":0}
Voltage=0
Vs ={"IA":0.85,"GT":0.85,"CLR":0.85}
Tempreture = 0
Ts ={"IA":30,"GT":30,"CLR":30}
EAK = 7e3
Stress = {"IA":0,"GT":0,"CLR":0}
C = 1
Seff={"IA":0,"GT":0,"CLR":0}
csv.DictReader
with open(File,"r+") as Fin:
reader = csv.DictReader(Fin, dialect='excel')
for line in reader:
for i in PP:
AFT[i] = math.exp(EAK*((1/Ts[i])-(1/float(line[i["T"]]))))
AFV[i] = math.exp(float(line[i["T"]])-Vs[i])
Stress[i] = AFT[i] * AFV[i]
Seff[i] = Seff[i]+Stress[i]
my problem is how do i get the value of the Key in dictionary i
AFT[i] = math.exp(EAK*((1/Ts[i])-(1/float(line[i["T"]]))))
in this case at the first loop i would like to get line["CTemp"]
any suggestions or different approach is welcome
you can either use python's built in locals() function:
>>> IA = {"V":"CVolt","T":"CTemp"}
>>> locals()['IA']
{'T': 'CTemp', 'V': 'CVolt'}
>>> locals()['IA']['T']
'CTemp'
or better, have your variables in one big dict like that:
>>> vars = {
'IA': {"V":"CVolt","T":"CTemp"},
'CLR': {"V":"CLR_Volt","T":"CLR_Temp"},
...
}
>>> vars['IA']
{'T': 'CTemp', 'V': 'CVolt'}
>>> vars['IA']['T']
'CTemp'
Thanks #damienfrancois to complete the answer with locals:
math.exp(EAK*((1/Ts[i])-(1/float(line[locals()[i]['T']]))))
with vars dict:
math.exp(EAK*((1/Ts[i])-(1/float(line[vars[i]['T']]))))
You can change your code like this
AFT[i] = math.exp(EAK*((1/Ts[i])-(1/float(line[eval(i)["T"]]))))
Note the use of eval to transform the string IA into the object named IA.
The use of locals(), or of a container dict is probably better though; see #Guy's answer.

python 3 saving a dictionary

I have looked at other questions on SO like this one but they are too techy for me to understand (only been learning a few days).
I am making a phonebook and i am trying to save a dictionary like so,
numbers = {}
def save(a):
x = open("phonebook.txt", "w")
for l in a:
x.write(l, a[l])
x.close()
But i get error write() only takes 1 argument and obv im passing 2, so my question is how can i do this in a beginner freindly way and could you describe it in a non techy way.
Thanks a lot.
It's better to use json module for dumping/loading dictionary to/from a file:
>>> import json
>>> numbers = {'1': 2, '3': 4, '5': 6}
>>> with open('numbers.txt', 'w') as f:
... json.dump(numbers, f)
>>> with open('numbers.txt', 'r') as f:
... print json.load(f)
...
{u'1': 2, u'3': 4, u'5': 6}
While JSON is a good choice and is cross-language and supported by browsers, Python has its own serialization format called pickle that is much more flexible.
import pickle
data = {'Spam': 10, 'Eggs': 5, 'Bacon': 11}
with open('/tmp/data.pickle', 'w') as pfile:
pickle.dump(data, pfile)
with open('/tmp/data.pickle', 'r') as pfile:
read_data = pickle.load(pfile)
print(read_data)
Pickle is Python-specific, doesn't work with other languages, and be careful to never load pickle data from untrusted sources (such as over the web) as it's not considered "safe".
Pickle works for other data types too, including instances of your own classes.
You need to use the json module and JSONEncode your dict, then you can use the module to write the new object to file.
When you read the file, you need to JSONDecode to convert it back into a python dict.
>>> import json
>>> d = {1:1, 2:2, 3:3}
>>> d
{1: 1, 2: 2, 3: 3}
>>> json.JSONEncoder().encode(d)
'{"1": 1, "2": 2, "3": 3}'
>>> with open('phonebook.txt', 'w') as f:
f.write(json.JSONEncoder().encode(d))
>>> with open('phonebook.txt', 'r') as f:
print f.readlines()
['{"1": 1, "2": 2, "3": 3}']

Categories

Resources