Save File Function - python

So for my intro programming class we have to create a game with a save/load function and I'm trying to test out some code to make sure it works.
For some reason I cannot get the following function to work properly. I've tried going through it line by line in the Idle and it works just fine there but once I try to use the same system in a function it just will not work. Help please?
def save(name,inventory,mapGrid,x,y,enemy):`
choice = 0
file = shelve.open("save_files")
save = {'save1':file['save1'],'save2':file['save2'],'save3':file['save3']}
print("Where would you like to save?")
print("Save 1 -", save['save1']['name'])
print("Save 2 -", save['save2']['name'])
print("Save 3 -", save['save3']['name'])
choice = input("Enter Number:\t")
if choice == 1:
save['save1']['name'] = name
save['save1']['inventory'] = inventory
save['save1']['mapGrid'] = mapGrid
save['save1']['x'] = x
save['save1']['y'] = y
save['save1']['enemy'] = enemy
file['save1'] = save['save1']
file.sync()
if choice == 2:
save['save2']['name'] = name
save['save2']['inventory'] = inventory
save['save2']['mapGrid'] = mapGrid
save['save2']['x'] = x
save['save2']['y'] = y
save['save2']['enemy'] = enemy
file['save2'] = save['save2']
file.sync()
if choice == 3:
save['save3']['name'] = name
save['save3']['inventory'] = inventory
save['save3']['mapGrid'] = mapGrid
save['save3']['x'] = x
save['save3']['y'] = y
save['save3']['enemy'] = enemy
file['save3'] = save['save3']
file.sync()
file.close()
print("Game Saved")
EDIT: After running the function it should save the dictionary to file['save#'] and allow me to access the data later on, but the data doesn't save to the shelve file and when I try to access it again there's nothing there. ((Sorry should have put this in right off the bat))
For example if I run the save() function again it should display the name associated with the save file, but it just shows 'EMPTY'.
The basic thing I have the save_files set to is
file['save#'] = {'name':'EMPTY'}

Since your if statements are comparing int, make sure that choice is also an integer. It's possible that choice is actually a string, in which case none of the comparisons will be True. Basically:
choice = int(input("Enter Number:\t"))
Alternatively you could change all comparisons to strings, but the important thing is to assure type consistency in the comparisons

Related

Issues with pickling in python - items not saving to file once program exits

I am trying to create a python program to save my friends' birthdays and access them easily and check for birthdays each day(I am not great at remembering dates and I never use facebook), but when I add a new birthday it is only accessible until I end the program - it then disappears again. I have been struggling with this for a while now and would really appreciate help fixing the error. Thanks!
import time
import pickle
def main():
birthday_file = open('birthdays_dict.dat','ab')
birthday_doc = open('birthdays_dict.dat','rb')
birthdays = pickle.load(birthday_doc)
date = time.strftime("%m/%d")
again = 'y'
while again.lower() == 'y' or again.lower() == 'yes':
choice = menu_choice()
if choice == 1:
name = add_name()
birthday = add_birthday()
birthdays[name] = birthday
print(name)
print(birthday)
pickle.dump(birthdays,birthday_file)
elif choice == 2:
print('Birthdays today(' + date + '):')
birth_today = {}
for key, value in birthdays.items():
if value == date:
print(key)
elif choice == 3:
search_name = input('Enter name to search: ')
print()
if search_name in birthdays:
print(birthdays[search_name])
if birthdays[search_name] == date:
print('Their birthday is today!')
else:
print('Not found')
else:
print('Not a valid selection!')
print()
again = go_again()
birthday_file.close()
birthday_doc.close()
Your problem is that you keep appending new dicts onto the file instead of replacing the old one, but then at startup you only load the very first one instead of all of them.
To fix this, you need to change this:
birthday_file = open('birthdays_dict.dat','ab')
… to this:
birthday_file = open('birthdays_dict.dat','wb')
But don't do that change on its own, because that will erase the file before you've read the old version!
You probably want to do something like this at the top of the function:
with open('birthdays_dict.dat', 'rb') as birthday_doc:
birthdays = pickle.load(birthday_doc)
I used a with statement so the file will automatically get closed right after the load, so it's definitely safe for us to overwrite it later.
Then later, when you want to write to the file, that's when you open it in w mode to erase the file and overwrite it with the new version—at which point you might as well close it immediately, because if you ever do write to it again, you're going to want to erase it again first, so let's use with again:
with open('birthdays_dict.dat', 'wb') as birthday_doc:
pickle.dump(birthdays, birthday_doc)

TicTacToe project in Python 2: I am trying to avoid using global variables and return variables instead

I am working on a project, and I have no idea how to avoid using global variables. I have a list of functions that perform bits and pieces but I am not able to pass variables between them!
Here is my current code:
===================
def player_names_input():
global player_A_name,player_B_name
player_A_name = raw_input("Please enter name for Player A : ")
player_B_name = raw_input("Please enter name for Player B : ")
def coin_flip():
global player_A_name,player_B_name,start_player,end_player,game_state
game_state = "running"
import random
print "\nFlipping a coin to see who starts first..."
random_int = random.randint(0, 1)
if random_int == 0:
coin = 'Heads'
start_player = player_A_name
end_player = player_B_name
else:
coin = 'Tails'
start_player = player_B_name
end_player = player_A_name
print '\nCoin flip --> ',coin
print '\nStarting player --> ',start_player
print '\nStarting player gets "X"'
player_names_input()
coin_flip()
Here is my failed attempt to use return instead of global:
=========================================================
def player_names_input():
player_A_name = raw_input("Please enter name for Player A : ")
player_B_name = raw_input("Please enter name for Player B : ")
return player_A_name,player_B_name
def coin_flip(player_A_name,player_B_name):
game_state = "running"
import random
print "\nFlipping a coin to see who starts first..."
random_int = random.randint(0, 1)
if random_int == 0:
coin = 'Heads'
start_player = player_A_name
end_player = player_B_name
else:
coin = 'Tails'
start_player = player_B_name
end_player = player_A_name
print '\nCoin flip --> ',coin
print '\nStarting player --> ',start_player
print '\nStarting player gets "X"'
player_names_input()
coin_flip(player_A_name,player_B_name)
1- Please help make my second code run, I really wanna avoid global variables as everyone recommends.
2- Please critique my code, I am in the beginning and I am trying to learn writing good code (not just code). How bad is my attempt?
Since you have defined player_names_input() to return a 2-tuple (the two values, player_A_name and player_B_name), you could just assign them like so in the scope you are using that function,
player_A_name, player_B_name = player_names_input()
Now, when this is called:
coin_flip(player_A_name, player_B_name)
The two variables will be available for use.
You may want to consider wrapping the actual main program in a main method like
def main():
player_A_name, player_B_name = player_names_input()
coin_flip(player_A_name, player_B_name)
And call that if that file was directly executed - this is done by checking the magic __name__ variable to equal to the string '__main__', so add this too to the end of your program file.
if __name__ == '__main__':
main()

Append Python returns instead of overwriting

I'm teaching myself Python and writing a simple GPA calculator. I have very little programming experience prior other than a college Java course, so bear with my code.
The premise is, the code will ask if you want to add a course to the list. If you do, it runs a function asking you the class name. Every time you add a class it'll ask if you want to add another. If you don't, it'll spit out a list of the classes you've added and then ask you to enter in the grades. I didn't get the grading part done yet. I don't think that will be too hard.
The problem is you can add a bunch of classes and it will only spit out the last one you entered. I'm assuming the issue is in askAgain(): classList = addClasses() because it keeps overwriting, but I'm not sure how to avoid a global variable (since they're bad?) and still keep this from overwriting itself. I seem to draw a blank when trying to figure out how to call something once to intialize it and not run it again. I've also read that conditional variables are bad, so I'm not sure what's best practice here. thanks
def main():
askAgain()
return 0
def askAgain():
while True:
addOrNot = raw_input("Add a class? [y/n]: ")
if addOrNot == "Y" or addOrNot == "y":
classList = addClasses() #This is probably where my issue is.
else:
try:
editClassGradeSelection = mainMenu(classList)
addGrades(editClassGradeSelection, classList)
except:
print("Hey you didn't add any classes yet.")
def addClasses():
try:
if classList in locals():
print("debug msg - classList exists")
except:
classList = []
classList.append(raw_input("Add class to the list: "))
return classList
def mainMenu(classList):
print("Here are the classes you've added: ")
counter = 0
for classes in classList:
print((str(counter+1)) + ". " + (str(classList[counter])) + "\n")
counter = counter + 1
while True:
editGrade = raw_input("Enter the number for the class grade to edit: ")
if int(editGrade) > len(classList) or int(editGrade) < 1:
print("Enter a proper number in the range listed.")
else:
break
return editGrade
def addGrades(editClassGradeSelection, classList):
print("debug stuff for now: ")
print((str(editClassGradeSelection)))
print((str(classList[:])))
if __name__ == '__main__':
main()
Although this snippet makes sure classlist is defined:
try:
if classList in locals():
print("debug msg - classList exists")
except:
classList = []
classlist is a local variable, hence everytime you run that function, classlist will be [], which probably explains why you can't ever display more than one. The classlist you assign it to gets reassigned to the one element of classlist (addClasses scope) every time this line is called:
classList = addClasses() #This is probably where my issue is.

Python function to give default value for blank entry not working

I have been trying to figure this out for way too long! What to do?
def fallBack(submission):
if (submission == ""):
submission = "fixed!"
return(submission)
name = input("What is your name?")
(fallBack(name))
location = input("Hi "+name+"! Nice to meet you, I live inside a computer, where do you live?")
I keep having the last input just print out nothing...
You need to store the result of fallBack().
Also, change fallBack() to return the original value if it is non-null:
def fallBack(submission):
if not submission:
return "fixed!"
else:
return submission
Then, use it like this:
name = fallBack(input("What is your name?"))
Just remove the brackets around fallBack(name)
def fallBack(submission):
if (submission == ""):
submission = "fixed!"
return submission
name = input("What is your name?")
name = fallBack(name)
location = input("Hi "+name+"! Nice to meet you, I live inside a computer, where do you live?")
Also remember that if using python 2.7 you should use raw_input instead of input
I'm not sure what you want to do, but I think this would do it:
def fallBack(submission):
if (submission == ""):
submission = "fixed!"
return (submission)
name = input("What is your name?")
name = fallBack(name)
location = input("Hi "+name+"! Nice to meet you, I live inside a computer, where do you live?")
Your two mistakes were not to return anything in case there is nothing to fix, and not to assin the value returned by the function.
By the way, there is a much more idiomatic way of doing this in Python:
name = input("What is your name?")
name = name or 'fixed!'
location = input("Hi "+name+"! Nice to meet you, I live inside a computer, where do you live?")
The second line tests if converting name to a boolean, and, if it returns False (for a string, it is equivalent to testing if it is not empty), replace it with 'fixed!'
The return is not well aligned! You are not returning anything unless submission is empty! :-)
def fallBack(submission):
if (submission == ""):
submission = "fixed!"
return(submission)

Saving/Loading lists in Python

I am new to python (and programming in general) and am making a database/register for a typical class. I wanted the user to be able to add and remove pupils from the database, I used lists primarily for this but have hit a stump.
Whenever I restart the program the list the user has modified returns back to the defualt list I specified in the code. I looked around the internet and tried to save the list onto a seperate txt file. However the txt file also goes back to the defualt every time I restart the program. I would like you to please give me a way to save the changes made to the list and keep them that way. Here is the code (it's not very good):
def menu():
print "*****************CLASS REGISTER*****************"
print "Press 1 See The List Of Pupils"
print "Press 2 To Add New Pupils"
print "Press 3 To Remove Pupils"
print "Press 0 To Quit \n"
filename = open('pupil.txt','r')
pupil = ["James Steele", "Blain Krontick", "Leeroy Jenkins", "Tanvir Choudrey"]
def see_list(x):
print x
def add_pupil(x):
print "You have chosen to add a new pupil.\n"
option = raw_input("Please type the childs name.")
x.append(option)
filename = open('pupil.txt','w')
filename.write('\n'.join(pupil))
filename.close()
print option, "has been added to the system."
return x
def delete_pupil(x):
print "You have chosen to remove a pupil.\n"
option = raw_input("Please type the childs name.")
if option in x:
x.remove(option)
filename = open('pupil.txt','w')
filename.write('\n'.join(pupil))
filename.close()
print option, "has been removed from the system."
else:
print "That person is not in the system."
return x
one = 1
while one != 0:
menu()
option = input()
if option == 1:
see_list(pupil)
elif option == 2:
add_pupil(pupil)
elif option == 3:
delete_pupil(pupil)
elif option == 0:
break
else:
print "That is not a valible choice."
filename = open('pupil.txt','w')
filename.write('\n'.join(pupil))
filename.close()
if option == 0:
quit
Well, you just open the pupil.txt file but never read back its contents. You need something like this:
filename = open('pupil.txt', 'r')
contents = filename.read()
filename.close()
pupil = [name for name in contents.split('\n') if name]
Also, you will need to handle the case when the pupil.txt file does not exist; this can be done with a try..except block around the IO calls.
Finally, as one of the comments has mentioned above, have a look at the pickle module, which lets you store a Python object in a file in Python's internal format (which is not really readable, but saves you a lot of hassle).
Not related to your question directly, but this:
one = 1
while one != 0:
...
is silly. All you need is:
while True:
...
This is what a database is for. Use sqlite - a simple file-based database the libraries for which come bundled with python.

Categories

Resources