Properly pickling and unpickling a dictionary - python

I've just started working with the Pickle module in Python 3.4.0 and trying to apply it to a simple program which handles Categories and Words. So far it stores everything as planned, but when I try to load back what I had dumped into the file, the structure appears to be empty:
new_data = int(input("New Data File?\n 1 = Yes\n 0 = No\nChoice: "))
if (new_data == 1):
f = open('data.txt', 'wb+')
data_d = {}
pickle.dump(data_d, f)
f.close()
PrMenu()
option = int(input("Option: "))
f = open('data.txt', 'rb+')
d = pickle.load(f)
#Functions inside this menu loop receive the structure (Dictionary)
#and modify it accordingly (add/modify/clear category/word), no
#pickling/unpickling is involved
while (option != 0):
if (option == 1):
add_c(d)
elif (option == 2):
modify_c(d)
elif (option == 3):
clear_c(d)
elif (option == 4):
add_w(d)
elif (option == 5):
modify_w(d)
elif (option == 6):
clear_w(d)
elif (option == 7):
pr_cw(d)
elif (option == 8):
pr_random(d)
if (option != 0):
PrMenu()
option = int(input("Option: "))
#the output structure would be eg. {category_a:[word1, word2, word3, ...], category_b:[..., ...]}
pickle.dump(d, f)
f.close()
print("End of Program")
I'm not sure where the problem is, I hope I was clear enough.
Thanks.

You are appending data to your file. so the first dataset is the empty dictionary, which you read in, and the second dataset is the filled dictionary, which you never read again. You have to seek back to 0 before writing.

Related

Run program but nothing comes out

I tried to run this program but it seems time only exit code 0.
if __name__ == '__main__':
import random
f = open("quiz.csv", 'r')
Counter =0
Content = f.read()
Colist = Content.split("\n")
qlist=[]
calist=[]
adict={}
alist=[]
c=0
for i in Colist:
if i:
if (Counter%5 ==0):
if(Counter!= 0):
x = alist[0]
random.shuffle(alist)
calist.append(alist.index(x))
c+=1
alist=[]
qlist.append(i)
else:
alist.append(i)
Counter+=1
x = alist[0]
random.shuffle(alist)
adict[c]= alist
calist.append(alist.index(x))
congo =["Goodjob!","awesome!","correct"]
cnt = 0
for i in range(len(qlist)):
print("\n question", i + 1)
print("-------")
print(qlist[i])
for j in range (len(adict[1])):
print(j+1, "->", adict[i][j])
ch = int(input("enter your choice: "))
if ((ch-1)==calist[i]):
random.shuffle(congo)
print(congo[0])
cnt+=1
else:
print("sry you chose the wrong option! the correct option is",calist[i]+1)
#print("\n End of quiz ! your score is", round(cnt/len(qlist)*100,2))
Can some one tell me what's wrong with this code? It's a school project which I need submit within 2 days time. Please give me some advice on this as I'm stuck at this stage for a long period of time.
Your loop is not correct. You're not saving the first question. I would skip reading and splitting the file, and just let the standard file do it.
counter = 0
qlist = []
alist = []
for line in open("quiz.csv"):
if line:
if counter % 5 == 0:
qlist.append( line )
alist.append( [] )
else:
alist[-1].append( line )
if counter % 5 == 4:
x = alist[-1][0]
random.shuffle(alist[-1])
calist.append(alist[-1].index(x))
counter += 1
Now you have qlist as the list of questions, alist as a list of lists, where entry [i] has the answers that map to question i, and calist has the index of the right answer.
Note that for this change to work, you must delete your "open", your "read", and your "split".

creating a list in python

I have an input list using which upon applying some if else logic while trying to save the output in a list. I'm when trying to check the type of it, found it to be "class list". I need to use this list and convert it to data frame in the next step so that i can have some terra data query written on top of it.
Also please note that upon writing the above piece of code in a single Jupiter window and when i go to the next Jupiter window and try query using the list index, i am always getting the last value in the list.
Need help in having the output set to a List, instead of Class List. also how to convert the list/Class list to a DataFrame?.
data = ['login', 'signup', 'account']
for i in range(len(data)):
source = []
if data[i] == 'login':
table = "sales.login_table"
elif data[i] == 'signup':
table = "sales.signup_table"
elif data[i] == 'account':
table = 'sales.account'
elif data[i] == 'addcc':
table = "sales.addcc"
elif data[i] == 'consolidatedfunding':
table = 'sales.consolidatedfunding'
elif data[i] == 'deposit':
table = 'sales.deposit'
elif data[i] == 'holdsassessment':
table = 'sales.holdsassessment'
elif data[i] == 'onboardinggc':
table = 'sales.onboardinggc'
source.append(table)
print(source)
print(source)
output:
['sales.login_table']
['sales.signup_table']
['sales.account']
print(type(source))
output :
<class 'list'>
You need to declare source = [] outside of for-loop, otherwise, in every iteration it'll be declare as empty list.
source = []
for i in range(len(data)):
if data[i] == 'login':
table = "sales.login_table"
elif data[i] == 'signup':
table = "sales.signup_table"
elif data[i] == 'account':
table = 'sales.account'
elif data[i] == 'addcc':
table = "sales.addcc"
elif data[i] == 'consolidatedfunding':
table = 'sales.consolidatedfunding'
elif data[i] == 'deposit':
table = 'sales.deposit'
elif data[i] == 'holdsassessment':
table = 'sales.holdsassessment'
elif data[i] == 'onboardinggc':
table = 'sales.onboardinggc'
source.append(table)
print(source)

Why do my dictionaries not update after I close the program?

I'm trying to create a program that will assign a hotel room number to the guests. After it is assigned, inside the dictionary, the value for the key should be updated into either 'Unavailable' or 'Reserved'. But, the thing is, after I close the program. Those room numbers that were updated becomes back into 'Available'.
Is there a way to change the value, so that it stays updated even after I close the program?
import math
f = open('room.txt', 'r+')
#Hotel Rooms
for i in range(1, 7):
locals()['Level{}'.format(i)] = {} # Creating Dictionary
start = 101
for x in range(1, 7):
for i in range(start, start + 10):
eval("Level" + str(x))[i] = 'Available' # Adding Values into Dictionary
start += 100
# heading function
def heading(number, header):
for i in range(60):
print('-', end = '')
print()
for i in range(number):
print('*', end = ' ')
print('\n' + header)
for i in range(number):
print('*', end = ' ')
print()
# customer details function
def customer():
print('''Room Types:
1 --> Single (Level 1)
2 --> Double (Level 2)
3 --> Triple (Level 3)
4 --> Quad (Level 4)
5 --> Queen (Level 5)
6 --> King (Level 6)
''')
room = input('Room Type: ')
name = input('Name: ')
hp = input('Mobile Number: ')
guests = input('Number of Guests: ')
arrival = input('Arrival Date(dd/mm/yyyy): ')
departure = input('Departure Date(dd/mm/yyyy): ')
confirm = input('Confirmation(Y/N): ')
conf(confirm, room, option)
# confirmation function + room for guest
def conf(con, num, opt):
if con == 'Y':
try:
for level, availability in eval('Level' + str(num)).items():
if availability == 'Available':
print('Guest Room Number:', level)
if option == '1':
eval('Level' + str(num))[level] = 'Reserved'
elif option == '2':
eval('Level' + str(num))[level] = 'Unavailable'
print('\nRoom Recorded!')
break
for i in range(1, 7):
f.write('Level ' + str(i) + '\n')
for key in eval('Level' + str(i)):
f.write(str(key) + ": " + eval('Level' + str(i))[key] + '\n')
f.write('\n')
f.close()
except NameError:
print('\nInvalid Room Type.')
elif con == 'N':
print('\nRecord Not Recorded.')
else:
print('\nInvalid Confirmation.')
# sub-headings (options)
def options():
print('''
Choose one of the following options (0-3):
0 <-- Back to Main Menu.
1 --> Booking Engine
2 --> Check In
3 --> Check Out''')
while True:
cus = '* Customer Registration *'
num = math.ceil(len(cus)/2)
heading(num, cus)
options()
option = input('Enter your option: ')
# Booking Engine
if option == '1':
boo = '* Booking Engine *'
num = math.ceil(len(boo)/2)
heading(num, boo)
customer()
#Check In
elif option == '2':
chein = '* Check In *'
num = math.ceil(len(chein)/2)
heading(num, chein)
customer()
else:
print("\nInvalid Option.")
continue
I haven't executed your code, but from what I see :
These are the first lines of your code :
f = open('room.txt', 'r+')
#Hotel Rooms
for i in range(1, 7):
locals()['Level{}'.format(i)] = {} # Creating Dictionary
start = 101
for x in range(1, 7):
for i in range(start, start + 10):
eval("Level" + str(x))[i] = 'Available' # Adding Values into Dictionary
start += 100
Here, you create a dictionary of all rooms, marking ALL of them as Available. It means that whatever the current value of a room, it will be marked as Available again.
Then in the conf function, you re-write the whole file, so the previously Reserved or Unavailable rooms are tagged as Available again.
Here is an example to be clear:
you start the program
You book a room, (e.g room 101), it is marked as Reserved
The rooms.txt file is saved with the correct value.
You stop your program
Then, when starting the program again:
A dict with ALL values set to Available is created. It means that even the room 101 is back to Available
You book any other room (e.g 201)
The dict is saved in your file. BUT remember that as you initialised your dict, all rooms where marked as Available again.
The problem, in fine is that you don't read your rooms.txt file when starting your program to actually load the state of each room in your dictionary.
I also recommend you to drop the custom data structure with which you save the file and go for a JSON file. It will simplify your code.

Setting variables in a function and importing them

I'm writing an adventure game, and I'm writing functions in different files, such as the saveGame function and read function. There are 4 main files, all interconnected. The main one is agMain.py. My issue is that I've imported one of my other files agRead.py, and call the function within that called read(). Here is the data for the agRead.py:
import os
import operator
import sys
import agSave
import agCreation
def read():
while True:
try:
file = open("agData.txt", "r")
except:
exec(open("agCreation.py").read())
break
break
file = open("agData.txt", "r")
data = file.readlines(0)
encrypFName = data[0]
encrypSName = data[1]
encrypAge = data[2]
encrypGender = data[3]
encrypHealth = data[4]
encrypMaxHealth = data[5]
encrypArmour = data[6]
encrypMaxArmour = data[7]
encrypHealthPotions = data[8]
encrypExp = data[9]
encrypMaxExp = data[10]
encrypLevel = data[11]
encrypGold = data[12]
encrypMaxGold = data[13]
encrypPowerLevel = data[14]
encrypMaxPowerExp = data[15]
encrypPowerExp = data[16]
encrypStage = data[17]
fName = encrypFName.strip()
sName = encrypSName.strip()
age = encrypAge.strip()
gender = encrypGender.strip()
health = encrypHealth.strip()
maxHealth = encrypMaxHealth.strip()
armour = encrypArmour.strip()
maxArmour = encrypArmour.strip()
healthPotions = encrypHealthPotions.strip()
exp = encrypExp.strip()
maxExp = encrypMaxExp.strip()
level = encrypLevel.strip()
gold = encrypGold.strip()
maxGold = encrypMaxGold.strip()
powerLevel = encrypPowerLevel.strip()
maxPowerExp = encrypMaxPowerExp.strip()
powerExp = encrypPowerExp.strip()
stage = encrypStage.strip()
As you can see, it sets variables such as stage and level. My agMain files however:
import os
import operator
import sys
import agSave
import agRead
while True:
agRead.read()
if (stage == 1):
exec(open("agStage1.py").read())
elif (stage == 2):
exec(open("agStage2.py").read())
elif (stage == 3):
exec(open("agStage3.py").read())
elif (stage == 4):
exec(open("agStage4.py").read())
elif (stage == 5):
exec(open("agStage5.py").read())
elif (stage == 6):
exec(open("agStage6.py").read())
elif (stage == 7):
exec(open("agStage7.py").read())
elif (stage == 8):
exec(open("ageStage8.py").read())
elif (stage == 9):
exec(open("agStage9.py").read())
elif (stage == 10):
exec(open("agStage10.py").read())
elif (stage > 10):
for i in range(100):
print("Game over!")
print("****************")
print("Well done, you have completed the game!")
exit()
else:
print("An error has occured.")
continue
As you can see here, it uses the stage when it from the function in the code. But it can't. If I run this, it says stage is not defined, like I hadn't run the function. Is it possible to set variables in a function, use the function, and use the variables in creates in a different file?
EDIT
At the time I made this, I had no knowledge of classes, so I apologise. Everyone who is having a similar problem (sharing variables between functions) just make a class with the functions you want as methods. It saves a lot of hassle!
https://docs.python.org/3/tutorial/controlflow.html#defining-functions:
More precisely, all variable assignments in a function store the value in the local symbol table; whereas variable references first look in the local symbol table, then in the local symbol tables of enclosing functions, then in the global symbol table, and finally in the table of built-in names. Thus, global variables cannot be directly assigned a value within a function (unless named in a global statement), although they may be referenced.
Assigning to a variable in a function implicitly creates a local variable in that function, unless you've declared it as global.
By using chaining, you can reduce the number of lines used and increase readability.
class Conf(object):
pass
def read():
while True:
try:
file = open("agData.txt", "r")
except:
exec(open("agCreation.py").read())
break
break
file = open("agData.txt", "r")
data = file.readlines(0)
conf = Conf()
conf.fName = data[0].strip()
conf.sName = data[1].strip()
conf.age = data[2].strip()
conf.gender = data[3].strip()
conf.health = data[4].strip()
conf.maxHealth = data[5].strip()
conf.armour = data[6].strip()
conf.maxArmour = data[7].strip()
conf.healthPotions = data[8].strip()
conf.exp = data[9].strip()
conf.maxExp = data[10].strip()
conf.level = data[11].strip()
conf.gold = data[12].strip()
conf.maxGold = data[13].strip()
conf.powerLevel = data[14].strip()
conf.maxPowerExp =data[15].strip()
conf.powerExp = data[16].strip()
conf.stage = data[17].strip()
return conf
You need to understand a little more about scoping. Inside a function, names that are bound by an assignment statement are created in the local namespace of the function call. This namespace is created when the function call is made and initialised with the values of the parameters bound to their names. When the function returns (or raises an exception) the namespace is deleted, and the names are no longer available.
Since you want to read lots of different values, consider creating an instance of a class. Instances also have a namespace, and names bound in that namespace will continue to be available until deleted or until the object is garbage collected.
After #Merlin published his helpful answer I decided to update this answer to include a data-driven version, reproduced below (but not tested). Thinking about this might lead you to a function that can create/initialise several different types of object.
Since execution speed is unlikely to be an issue I preferred an approach that was more generalised.
class Conf(object):
pass
def read():
while True:
try:
file = open("agData.txt", "r")
except:
exec(open("agCreation.py").read())
break
break
file = open("agData.txt", "r")
conf = Conf()
names = ["fName", "sName", "age", "gender", "health", "maxHealth",
"armour", "maxArmour", "healthPotions", "exp", "maxExp",
"level", "gold", "maxGold", "powerLevel", "maxPowerExp",
"powerExp", "stage"]
for name in names:
setattr(conf, name, next(file).strip()
return conf
The variables are only visible from inside read.
Contain the variables you want to use by doing something like this.
agRead.py
class Conf(object):
pass
def read():
while True:
try:
file = open("agData.txt", "r")
except:
exec(open("agCreation.py").read())
break
break
file = open("agData.txt", "r")
data = file.readlines(0)
encrypFName = data[0]
encrypSName = data[1]
encrypAge = data[2]
encrypGender = data[3]
encrypHealth = data[4]
encrypMaxHealth = data[5]
encrypArmour = data[6]
encrypMaxArmour = data[7]
encrypHealthPotions = data[8]
encrypExp = data[9]
encrypMaxExp = data[10]
encrypLevel = data[11]
encrypGold = data[12]
encrypMaxGold = data[13]
encrypPowerLevel = data[14]
encrypMaxPowerExp = data[15]
encrypPowerExp = data[16]
encrypStage = data[17]
conf = Conf()
conf.fName = encrypFName.strip()
conf.sName = encrypSName.strip()
conf.age = encrypAge.strip()
conf.gender = encrypGender.strip()
conf.health = encrypHealth.strip()
conf.maxHealth = encrypMaxHealth.strip()
conf.armour = encrypArmour.strip()
conf.maxArmour = encrypArmour.strip()
conf.healthPotions = encrypHealthPotions.strip()
conf.exp = encrypExp.strip()
conf.maxExp = encrypMaxExp.strip()
conf.level = encrypLevel.strip()
conf.gold = encrypGold.strip()
conf.maxGold = encrypMaxGold.strip()
conf.powerLevel = encrypPowerLevel.strip()
conf.maxPowerExp = encrypMaxPowerExp.strip()
conf.powerExp = encrypPowerExp.strip()
conf.stage = encrypStage.strip()
return conf
and agMain.py
import agRead
while True:
conf = agRead.read()
if conf.stage == 1:
Yes it's possible, but variable would be available only after function execution:
### file agRead.py ###
def read():
# some code there
read.my_super_var = 'value'
### file agMain.py ###
import agRead
agRead.read()
print(agRead.read.my_super_var) # value
Okay, so I have worked this out. Thanks to everyone who answered, but holdenweb and nightcrawler especially. I have created a class in the agRead.py, and put all of the variables as a part of that class, before returning the class. Here is my agRead.py now:
import os
import operator
import sys
import agSave
import agCreation
class Conf(object):
pass
# READ FUNCTION
def read():
try:
open("agData.txt", "r")
except:
exec(open("agCreation.py").read())
file = open("agData.txt", "r")
data = file.readlines(0)
encrypFName = data[0]
encrypSName = data[1]
encrypAge = data[2]
encrypGender = data[3]
encrypHealth = data[4]
encrypMaxHealth = data[5]
encrypArmour = data[6]
encrypMaxArmour = data[7]
encrypHealthPotions = data[8]
encrypExp = data[9]
encrypMaxExp = data[10]
encrypLevel = data[11]
encrypGold = data[12]
encrypMaxGold = data[13]
encrypPowerLevel = data[14]
encrypMaxPowerExp = data[15]
encrypPowerExp = data[16]
encrypStage = data[17]
conf = Conf()
conf.fName = encrypFName.strip()
conf.sName = encrypSName.strip()
conf.age = encrypAge.strip()
conf.gender = encrypGender.strip()
conf.health = encrypHealth.strip()
conf.maxHealth = encrypMaxHealth.strip()
conf.armour = encrypArmour.strip()
conf.maxArmour = encrypArmour.strip()
conf.healthPotions = encrypHealthPotions.strip()
conf.exp = encrypExp.strip()
conf.maxExp = encrypMaxExp.strip()
conf.level = encrypLevel.strip()
conf.gold = encrypGold.strip()
conf.maxGold = encrypMaxGold.strip()
conf.powerLevel = encrypPowerLevel.strip()
conf.maxPowerExp = encrypMaxPowerExp.strip()
conf.powerExp = encrypPowerExp.strip()
conf.stage = encrypStage.strip()
return conf
and my agMain.py:
# Main
# Will open a stage depending on the stage the user is at.
import os
import operator
import sys
import agSave
import agRead
#Read the file
while True:
agRead.read()
if (conf.stage == 1):
exec(open("agStage1.py").read())
elif (conf.stage == 2):
exec(open("agStage2.py").read())
elif (conf.stage == 3):
exec(open("agStage3.py").read())
elif (conf.stage == 4):
exec(open("agStage4.py").read())
elif (conf.stage == 5):
exec(open("agStage5.py").read())
elif (conf.stage == 6):
exec(open("agStage6.py").read())
elif (conf.stage == 7):
exec(open("agStage7.py").read())
elif (conf.stage == 8):
exec(open("ageStage8.py").read())
elif (conf.stage == 9):
exec(open("agStage9.py").read())
elif (conf.stage == 10):
exec(open("agStage10.py").read())
elif (conf.stage > 10):
for i in range(100):
print("Game over!")
print("****************")
print("Well done, you have completed the game!")
exit()
else:
print("An error has occured.")
continue
And this works perfectly, thank you everyone! This is an amazing community, and I hope to become a real member of it! Thanks again!

Fizzbuzz (Turning my output to a string?)

New here and hoping I can help as much as I am helped. Basically, I have been tasked with writing a fizzbuzz program in Python and so far so good except for some feedback I received.
Now I have to ensure that the output of my program comes across horizontally and is not printed vertically on new lines. From my understanding, and my lecturers hinting, I need to turn function to produce strings and remove the print statements as well.
Code is below:
def fizzbuzz1 (num):
for num in range(1, num):
if (num%3 == 0) and (num%5 == 0):
print("Fizzbuzz")
elif ((num % 3) == 0):
print("Fizz")
elif ((num % 5) == 0):
print("buzz")
else :
print (num)
def main ():
while True: #Just to keep my program up and running while I play with it
num = input ("please type a number: ") #
num = int (num)
print ("Please select an type what option you wish to try: A) Is this Fizz or Buzz? B) Count saying fizz/buzz/fizzbuzz")
opt = input ("Please type A or B and press enter: ")
if opt == "A":
fizzbuzz(num)
elif (opt == "a")
fizzbuzz(num)
elif (opt == "B"):
print (fizzbuzz1(num))
elif (opt == "b"):
print (fizzbuzz1(num))
main ()
I have tried a whole host of things, and my lecturer doesn't seem too interested in help me. Womp. I was recommended to review this exercise were I played with this piece of code:
def func(num):
value = ‘’
for x in range(...):
if .... == .... :
value += str(x) + ‘, ‘
return value[…]# You need to remove the last comma and the space
When I do play with this code, I do get numbers to go across the screen. But for the life of me I can not seem to incorporate what I have written with elements from this. Where am I going astray?
Thank you for any and all your advice/help. If you do choose to reply, please keep it as simple as possible for me.
Cheers.
Update: Thanks everyone for your suggestions, lots of thimgs I didnt know to try!
I also found a thread here at: Can't figure out how to print horizontally in python?
Which has answers to a similar issue.
Try printing without a new line, if you use Python 3.x
def fizzbuzz1 (num):
for num in range(1, num):
if (num%3 == 0) and (num%5 == 0):
print("Fizzbuzz ", end="")
elif ((num % 3) == 0):
print("Fizz ", end="")
elif ((num % 5) == 0):
print("buzz ", end="")
else:
print ( str(num) + " ")
print(" ")
You're very close. The approach I would take would be to store the results in a list, then join the contents of the list to make the output string. Here's an example:
>>> def fizzbuzz1(num):
... fb = []
...
... # Iterate through the range, then use `fb.append()` to append the
... # new element to the end of the list.
... for n in range(1, num):
... if not (n%3 or n%5):
... fb.append('Fizzbuzz')
... elif not n%3:
... fb.append('Fizz')
... elif not n%5:
... fb.append('Buzz')
... else:
... fb.append(str(n))
...
... return ', '.join(fb)
...
>>> fizzbuzz1(20)
'1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, 11, Fizz, 13, 14, Fizzbuzz, 16, 17, Fizz, 19'
>>>

Categories

Resources