0

I am working through the chapter exercises in Tony Gaddis's "Starting Out With Python" 3rd edition from a class I have taken previously. I'm in chapter 9 and Exercise 8 requires me to write a program that pickles a dictionary (name:email) to a file when it closes and unpickles that file retaining the data when it is opened. I have read every word in that chapter and I still don't understand how you can do both in the same file. When you use the open function it creates a file which, in my understanding, is a new file with no data. I'm thinking it may be a sequencing issue, as in where to put the dump and load lines of code but that doesn't make sense either. Logic dictates you have to open the file before you can dump to it.

If the 'open' function creates a file object and associates it with a file and this function appears early in the code (as in def main), what keeps it from zeroing out the file each time that line is called?

This is not a homework assignment. I have completed that class. I am doing this for my own edification and would appreciate any explanation which would help me to understand it. I have included my attempt at the solution which is reflected in the code below and will keep gnawing at it until I find the solution. I just thought since the gene pool is deeper here I would save myself some time and frustration. Thank you very much to those that choose to reply and if I am lacking in any pertinent data that would help to clarify this issue, please let me know.

import pickle

#global constants for menu choices
ADDNEW = 1
LOOKUP = 2
CHANGE = 3
DELETE = 4
EXIT = 5

#create the main function
def main():

    #open the previously saved file
    friends_file = open('friends1.txt', 'rb')
    #friends = pickle.load(friends_file)
    end_of_file = False
    while not end_of_file:
        try:
            friends = pickle.load(friends_file)
            print(friends[name])
        except EOFError:
            end_of_file = True
        friends_file.close()

    #initialize variable for user's choice
    choice = 0

    while choice != EXIT:
        choice = get_menu_choice() #get user's menu choice

        #process the choice
        if choice == LOOKUP:
            lookup(friends)
        elif choice == ADDNEW:
            add(friends)
        elif choice == CHANGE:
            change(friends)
        elif choice == DELETE:
            delete(friends)

#menu choice function displays the menu and gets a validated choice from the user
def get_menu_choice():
    print()
    print('Friends and Their Email Addresses')
    print('---------------------------------')

    print('1. Add a new email')
    print('2. Look up an email')
    print('3. Change a email')
    print('4. Delete a email')
    print('5. Exit the program')
    print()

    #get the user's choice
    choice = int(input('Enter your choice: '))

    #validate the choice
    while choice < ADDNEW or choice > EXIT:
        choice = int(input('Enter a valid choice: '))
    #return the user's choice
    return choice

#the add function adds a new entry into the dictionary
def add(friends):

    #open a file to write to
    friends_file = open('friends1.txt', 'wb')

    #loop to add data to dictionary
    again = 'y'    
    while again.lower() == 'y':

        #get a name and email
        name = input('Enter a name: ')
        email = input('Enter the email address: ')

        #if the name does not exist add it
        if name not in friends:
            friends[name] = email
        else:
            print('That entry already exists')
            print()

        #add more names and emails
        again = input('Enter another person? (y/n): ')

    #save dictionary to a binary file
    pickle.dump(friends, friends1.txt)
    friends1.close()

#lookup function looks up a name in the dictionary
def lookup(friends):

    #get a name to look up
    name = input('Enter a name: ')

    #look it up in the dictionary
    print(friends.get(name, 'That name was not found.'))

#the change function changes an existing entry in the dictionary
def change(friends):
    #get a name to look up
    name = input('Enter a name: ')

    if name in friends:
        #get a new email
        email = input('Enter the new email address: ')

        #update the entry
        friends[name] = email
    else:
        print('That name is not found.')

#delete an entry from the dictionary
def delete(friends):
    #get a name to look up
    name = input('Enter a name: ')
    #if the name is found delete the entry
    if name in friends:
        del [name]
    else:
        print('That name is not found.')

#call the main function
main()

2 Answers2

0

If you open a file for reading with open("my_file","r") it will not change the file. The file must already exist. If you open a file for writing with open("my_file","w") it will create a new file, overwriting the old one if it exists. The first form (reading) is the default so you can omit the second "r" argument if you want. This is documented in the Python standard library docs.

Paul Cornelius
  • 9,245
  • 1
  • 15
  • 24
  • Thank you for your response. I read the docs but it still didn't clarify my question. Hypothetically, I open the file initially which creates an empty file and add some data to that file then dump it using a binary stream. Since I need to append binary data to that same file in the future, should I still open it in the "r" mode or should it be opened in the "rb" mode? – tfwynne Mar 15 '16 at 02:23
  • Thank you Paul Cornelius for your response. I read the docs but it still didn't clarify my question. Hypothetically, I open the file initially which creates an empty file and add some data to that file then dump it using a binary stream. Since I need to append binary data to that same file in the future, should I still open it in the "r" mode or should it be opened in the "rb" mode? Ch 9 mentions writing in the binary mode but I am assuming that is for new files. Ch 6 mentions an "a" mode which appends to an open file. Can the "a" mode be used in conjunction with binary writing? Thanks again. – tfwynne Mar 15 '16 at 02:30
  • If you need to write binary data append the "b" to the file mode character. I don't know why you assume that it's only for a new file. It isn't. If you need to append to already existing file, then open it in the "a" mode. "ab" means append to a binary file. I am confused by your statement "add some data to that file and dump it using a binary stream" since those are the same thing. The are only two things a file can do: read and write. Appending is just like writing, but you start writing at the end of an existing file instead of from scratch. – Paul Cornelius Mar 15 '16 at 04:33
0

Use open("myfile", 'r+') this allows both read and write functions. (at least in 2.7)