Writing and retrieving pickled object to a file - python

I'm doing creating a address book for a computer science class, where we are supposed to have a list of objects "contact" written to a file when the program closes and read from the file when the program starts. However, after the data is written to the file, once it is read it does not seem to keep its object form.
import pickle
class Contact:
#Creating the class with the attributes I want
def __init__(self, firstname, lastname, number, areacode, city):
self.firstname = firstname
self.lastname = lastname
self.number = number
self.areacode = areacode
self.city = city
def __str__(self):
return "({0} {1}, {2}, {3}, {4})".format(self.firstname, self.lastname, self.number, self.areacode, self.city)
#reading the object
def opendata():
readable = []
addresses = []
A = open("Address_book", "rb+")
addresses = A.read()
A.close
B = len(addresses)
if B != 0:
readable = pickle.loads(addresses)
return readable
else:
return addresses
def savedata(file):
addresses = open("Address_book", "wb+")
temp = pickle.dumps(file)
addresses.write(temp)
addresses.close()
def Address_manager():
Address = []
fromfile = opendata()
Address.append(fromfile)
while True:
print("add = add contact, modify = modify contact, search = search contacts, end = close program, print = print full list")
A = input("What do you want to do?: ")
if A == "end":
savedata(Address)
break
else:
if A == "print":
for i in Address:
print(str(i))
print("")
continue
elif A == "add":
Address.append(add_contact())
print("")
continue
elif A == "search":
lists2 = search_contact(Address)
A = 0
for i in lists2:
A += 1
print(A, str(i))
print("")
print("")
continue
elif A == "modify":
modified = modify_contact(Address)
Address.append(modified)
print("")
continue
def add_contact():
while True:
try:
A = Contact(input("First name: "), input("Last name: "), input("Phone Number: "), input("Area Code: "), input("City: "))
print(str(A))
B = input("Is this right?: (y/n)")
if B == "y":
print("Well done?")
return A
else:
print("Try Again")
continue
except:
print("bad data")
If I try to "print" the list after getting it from the file it prints them in the wrong form. What am I doing wrong and why?
Edit 1: I apologize for the less than efficient code.
Edit 2: Added function to add contact

Related

call class attributer in a class menu

I am probably making a big mess right now... But I want to create a menu that can activate different classes that holds attributes. What would be the easiest way to write this?
import replit
class Logistics_System():
print("Welcome to Express Delivery")
user = []
def menu(self):
while True:
print("")
print("[1]. Add/remove/update: user to the system.")
print("[2]. Add/remove/update: corporate customer.")
print("[3]. Add/remove/update: private customer.")
print("[4]. Add bike to the system.")
print("[5]. Add Truck to the system.")
print("[6]. Add Ship to the system.")
print("[7]. Create shipment/order of items. ")
print("[8]. Add Items to a shipment.")
print("[9]. Update status of order.")
print("")
try:
option = int(input("Choose from the menu: "))
if option == 1:
b.User()
else:
print("Program quits")
break
except:
print("Wrong value!")
self.menu()
b = Logistics_System()
b.menu()
class User(Logistics_System):
user_list = []
def __init__(self, first, last, id, adress, number, email, password, path):
self.first = first
self.last = last
self.email = first + '.' + last + '#expressdelivery.com'
self.id = id
self.adress = adress
self.number = number
self.password = password
def user_input():
try:
first = input("First name: ")
last = input("Last name: ")
id = input("ID: ")
adress = input("Adress: ")
number = int(input("Number: "))
if user_list >= 0:
user_list.append([first, last, email, id, adress, number, password])
except:
print("Wrong value!")
I wanted to save these values to a csv file so I can remove data or add data when I need to

How to create an object specific list that doesn't empty itself when called more than once

My problem
in init I declare two list variables that are called nlist and rlist.
Then in method add_neighour I am appending object (router2) named router2.__routername to the list of object called self.nlist.
class Router:
def __init__(self, routername):
self.__routername = routername
self.nlist = []
self.rlist = []
def print_info(self):
print(self.nlist)
print(" ", self.__routername, sep="")
print(" N: ", ", ".join(sorted(self.nlist)), sep="")
print(" R: ", ", ".join(sorted(self.rlist)), sep="")
def add_neighbour(self, router2):
self.nlist.append(router2.__routername)
print(self.nlist)
I'm calling the code inside the while True that waits for a specific commmand:
Command P is for printing info
if command == "P":
routername = input("Enter router name: ")
if routername not in mydict:
print("Router was not found.")
else:
router = Router(routername)
router.print_info()
Command C is for chaining two routers together. (for example appending router2s name router2.__routername to the neighbour list self.nlist of router1.
This happens class Router inside the method add_neighbour that takes another router as parameter.
elif command == "C":
router1 = input("Enter 1st router: ")
router2 = input("Enter 2nd router: ")
router1 = Router(router1)
router2 = Router(router2)
router1.add_neighbour(router2)
router2.add_neighbour(router1)
The appending goes fine and when I print(self.nlist) at the end it shows up that the list has been updated with the appended element I wanted. However, when calling the print_info function and trying to print the sorted(self.nlist) It prints an empty list.
I have no clue why. Should I declare the object specific list in a different way/place?
or
append values to the list differently?
my goal is to: succesfully print self.nlist inside the print_info method. Succesfully printing meaning that it prints something else than an empty list.
I tried looking for answers from several posts. Sorry if this post is duplicate and horribly written.
The whole code: (in progress as you can see...)
class Router:
def __init__(self, routername):
self.__routername = routername
self.nlist = []
self.rlist = []
def print_info(self):
print(self.nlist)
print(" ", self.__routername, sep="")
print(" N: ", ", ".join(sorted(self.nlist)), sep="")
print(" R: ", ", ".join(sorted(self.rlist)), sep="")
def add_neighbour(self, router2):
self.nlist.append(router2.__routername)
print(self.nlist)
def main():
mydict = {}
routerfile = input("Network file: ")
while True:
command = input("> ")
command = command.upper()
if command == "P":
routername = input("Enter router name: ")
if routername not in mydict:
print("Router was not found.")
else:
router = Router(routername)
router.print_info()
pass
elif command == "PA":
pass
elif command == "S":
pass
elif command == "C":
router1 = input("Enter 1st router: ")
router2 = input("Enter 2nd router: ")
router1 = Router(router1)
router2 = Router(router2)
router1.add_neighbour(router2)
router2.add_neighbour(router1)
pass
elif command == "RR":
pass
elif command == "NR":
routername = input("Enter a new name: ")
router = Router(routername)
if routername not in mydict:
mydict[routername] = router
else:
print("Name is taken.")
pass
elif command == "NN":
pass
elif command == "Q":
print("Simulator closes.")
return
else:
print("Erroneous command!")
print("Enter one of these commands:")
print("NR (new router)")
print("P (print)")
print("C (connect)")
print("NN (new network)")
print("PA (print all)")
print("S (send routing tables)")
print("RR (route request)")
print("Q (quit)")
main()

File Access in python

Whenever I go to load a text file for my program it displays the info in the text file yet when I input the roster function it does not display the text file and show it is available to be modified. Is it something with how I created the text file in the first place or is my coding for loadData not written correctly i think i may be confused on the difference between just setting up a function just to read back the file instead of actually opening the text file to be able to modify it.
dict_member = {}
players = dict_member
class Players:
def __init__(self, name, number, jersey):
self.name = name
self.number = number
self.jersey = jersey
def display(self):
print('Printing current members\n')
for number, player in dict_member.items():
print(player.name + ', ' + player.number + ', ' + player.jersey)
def add(self):
nam = input("Enter Player Name\n ")
numb = input("Enter Player Number\n ")
jers = input("Enter Jersey Number\n ")
dict_member[nam] = Players(nam, numb, jers)
def remove(self, name):
if name in dict_member:
del dict_member[name]
def edit(self, name):
if name in dict_member:
nam = input("Enter Different Name\n")
num = input("Enter New Number\n ")
jers = input("Enter New Jersey Number\n ")
del dict_member[name]
dict_member[name] = Players(nam, num, jers)
else:
print("No such player exists")
def saveData(self):
roster = input("Filename to save: ")
print("Saving data...")
with open(roster, "r+") as rstr:
for number, player in dict_member.items():
rstr.write(player.name + ', ' + player.number + ', ' + player.jersey)
print("Data saved.")
rstr.close()
def loadData(self):
dict_member = {}
roster = input("Filename to load: ")
file = open(roster, "r")
while True:
inLine = file.readline()
if not inLine:
'break'
inLine = inLine[:-1]
name, number, jersey = inLine.split(",")
dict_member[name] = (name, number, jersey)
print("Data Loaded Successfully.")
file.close()
return dict_member
def display_menu():
print("")
print("1. Roster ")
print("2. Add")
print("3. Remove ")
print("4. Edit ")
print("5. Save")
print("6. Load")
print("9. Exit ")
print("")
return int(input("Selection> "))
print("Welcome to the Team Manager")
player_instance = Players(None, None, None)
menu_item = display_menu()
while menu_item != 9:
if menu_item == 1:
player_instance.display()
elif menu_item == 2:
player_instance.add()
elif menu_item == 3:
m = input("Enter Player to Remove\n")
player_instance.remove(m)
elif menu_item == 4:
m = input("Enter Player to Edit\n")
player_instance.edit(m)
elif menu_item == 5:
player_instance.saveData()
elif menu_item == 6:
player_instance.loadData()
menu_item = display_menu()
print("Exiting Program...")
Try this:
def loadData(self):
file = open(input("Filename to load: "), "r")
text = file.read()
file.close()
for line in text:
name, number, jersey = (line.rstrip()).split(',')
dict_member[name] = (name, number, jersey)
print("Data Loaded Successfully.")
return dict_member
def saveData(self, dict_member):
file = open(input("Filename to save: "), "a")
for number, player in dict_member.items():
rstr.write(player.name + ', ' + player.number + ', ' + player.jersey)
print("Data saved.")
file.close()
What I think was the error was you using "break" in string from instead of the command, break (no quotes required). I optimized the code a little so maybe it will work now? If not, what exactly happens? Try debugging as well as checking your file.
you didnt load your data into dict_member before displaying the roster
when you load your data in the loadData function you redefine dict_member
so it will "shadow" the outer dict_member so when the display function is called dict_member will always be empty
so you probably want to remove this line
def loadData(self):
# **remove this line --->** dict_member = {}
roster = input("Filename to load: ")
file = open(roster, "r")
while True:
inLine = file.readline()
if not inLine:
break
inLine = inLine[:-1]
name, number, jersey = inLine.split(",")
dict_member[name] = (name, number, jersey)
print("Data Loaded Successfully.")
file.close()
return dict_member

Why are some variables not defined?

This is what I have to do:
Look up and print the student GPA
Add a new student to the class
Change the GPA of a student
Change the expected grade of a student
Print the data of all the students in a tabular format
Quit the program
import student
import pickle
lookup = 1
change = 2
add = 3
delete = 4
QUIT = 0
FILENAME = 'student.dat'
def main():
students_info = load_students()
choice = 0
load_students()
#add(students_info)
change_grade(students_info)
change_GPA(students_info)
#get_menu_choice()
look_up(students_info)
while choice != QUIT:
choice = get_menu_choice()
if choice == lookup:
look_up(students_info)
elif choice == add:
add(students_info)
elif choice == change:
change(students_info)
elif choice == delete:
delete(students_info)
save_students(students_info)
def load_students():
try:
input_file = open(FILENAME, 'rb')
students_dict = pickle.load(input_file)
input_file.close()
except IOError:
students_dict = {}
print(students_dict)
return students_dict
def get_menu_choice():
print()
print('Menu')
print("-------------------")
print('1. Look up ID')
print('2.....')
choice = int(input("Enter your choice:"))
return choice
def look_up(students_info):
ID = input('Enter ID:')
print(student_info.get(ID, "Not found!"))
## try:
## print(students_info[ID])
## except KeyError:
## print("Not found!")
def change_GPA(students_info):
ID = input("ID:")
if ID in students_info:
GPA= float(input("New GPA:"))
students=student.Student(ID,GPA,grade,work)
students_info[ID] = students
print ("This",students_info[ID])
else:
print("Not found!")
def change_grade(students_info):
ID = input("ID:")
if ID in students_info:
New_grade = input("Enter new grade:")
students=student.Student(ID,GPA,grade,work)
students_info[ID] = students
#new_grade = students_info[name]
else:
print("Not found!")
def add(students_info):
name = input("Enter the student name:")
ID= input("Enter student's ID:")
GPA= float(input("Enter GPA:"))
grade= input("Enter student's expected grade:")
work = input("Does the student work part time or full time?")
students=student.Student(name,ID,GPA,grade,work)
print(students_info['ID'])
def save_students(students_info):
output_file = open(FILENAME, 'wb')
pickle.dump(students_info, output_file)
output_file.close()
main()
Whenever I tried to change the GPA or grade it's not defined. How could I change one value from the dictionary studens_info?
As gus42 has commented, the errors you are getting are from the lines:
students=student.Student(ID,GPA,grade,work)
You've not defined grade or work in either of the places you do this (nor GPA in change_grade), so it should not be surprising that you're getting an error.
I think there are two ways to fix the issue:
The simplest way is to change your logic from creating a new Student object to modifying the one that already exists. I don't know exactly what the attribute names are in your Student class, but here's a reasonable guess at a solution:
def change_GPA(students_info):
ID = input("ID:")
if ID in students_info:
GPA= float(input("New GPA:"))
students_info[ID].GPA = GPA # assign new GPA to old student object
else:
print("Not found!")
def change_grade(students_info):
ID = input("ID:")
if ID in students_info:
grade = input("Enter new grade:")
students_info[ID].grade = grade # assign new grade to existing student object
else:
print("Not found!")
The other option is to replace the existing Student object with a new one with some different values. This is close to what your current code, but it only really makes sense if your Student objects are immutable (perhaps because you made the type with namedtuple?). To make it work (where your current code does not), you'll have to load the old values from the old Student object before making the new object:
def change_GPA(students_info):
ID = input("ID:")
if ID in students_info:
new_GPA = float(input("New GPA:"))
old_grade = students_info[ID].grade # load old values
old_work = students_info[ID].work
new_student = students.Student(ID, new_GPA, old_grade, old_work)
students_info[ID] = new_student # replace the old student with a new object
else:
print("Not found!")
def change_grade(students_info):
ID = input("ID:")
if ID in students_info:
new_grade = input("Enter new grade:")
old_GPA = students_info[ID].GPA
old_work = students_info[ID].work
new_student = students.Student(ID, old_GPA, new_grade, old_work)
students_info[ID] = new_student
else:
print("Not found!")

Pickle file with many objects

I cannot get my file to store multiple instances of contacts. After adding new contact and trying to print them, it comes up with "IndexError: list index out of range" error. What shall I do to make it work?
import pickle
class People():
def __init__(self, name, surname, age, mobile_no, home_no):
self.name = name
self.surname = surname
self.age = age
self.mobile_no = mobile_no
self.home_no = home_no
def DisplayContacts(self):
print("First Name: \t", self.name)
print("Surname: \t", self.surname)
print("Age: \t", self.age)
print("Mobile Number: \t", self.mobile_no)
print("Home Number: \t", self.home_no)
print()
def addContact():
newname = str(input("First name: \t"))
newsurname = str(input("Surname: \t"))
newage = int(input("Age: \t"))
newmobile_no = int(input("Mobile Number: \t"))
newhome_no = int(input("Home Number: \t"))
newContact = People(newname, newsurname, newage, newmobile_no, newhome_no)
return newContact
cont = 1
contacts = []
while cont == 1:
user = input("Do you want to add contact? (Y/N)")
if user == "Y" or user == "y":
print ("works")
contacts.append(addContact())
file = open("CList.pickle", "ab")
pickle.dump(contacts, file, pickle.HIGHEST_PROTOCOL)
file.close()
else:
print ("111")
cont = 0
useropen = input("open file? (Y/N)")
if useropen == "Y" or useropen == "y":
with open ("CList.pickle", "rb") as pickled_file:
contacts = pickle.load(pickled_file)
print(contacts[0].surname)
print(contacts[1].surname)
else:
print("Null")
Simply appending a picked object to a file is not the same thing as pickling a list. EAch time you append, you've created another pickled record. Read the file multiple times to get your list:
with open ("CList.pickle", "rb") as pickled_file:
contacts = []
try:
while True:
contacts.append(pickle.load(pickled_file))
except EOFError:
pass
Now, instead of appending the list of contacts (which would give you a list of lists with many duplicates), just pickle the new contact:
with open("CList.pickle", "ab") as _file:
while True:
user = input("Do you want to add contact? (Y/N)")
if user == "Y" or user == "y":
print ("works")
pickle.dump(addContact(), _file, pickle.HIGHEST_PROTOCOL)
else:
print ("111")
break

Categories

Resources