0

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") 
1
  • Looks like each time you make a new contact, you open the file and append the pickled object to the existing data there. Are you sure that's allowed? I don't think pickle.dumps(a) + pickle.dumps(b) is the same as pickle.dumps([a,b]). Commented Jun 19, 2014 at 19:41

1 Answer 1

1

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
Sign up to request clarification or add additional context in comments.

5 Comments

@JoeDoe - have you changed the object you are pickling? You could have old cruft in the file - deleting and starting over may help. I also realized I didn't note that you should change how you pickle also... just pickle the contact object, not the list of contact objects. I am making an update to the anwser.
I did all as you suggested but when I try to load the file it's just a empty prompt
I ran the patched up code and found that dump/load aren't quite symatric. You end up with an extra new line, so the loop that reads the records gets Person, None, Person, None, ... Solving this is mildly annoying, you could for instance prepend each write with the length of the thing you are writing, or more easily just skip the Nones.
and what would be the way to skip those?
One option is to load into a variable and then check if its None before adding to the list. Another is to build up your own records using ctypes. Pickle into a string and then use ctypes to write a record of length,pickled_string. The reader would read length-ed chunks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.