Zachary Matthew Perry
Zachary Matthew Perry

Reputation: 53

Using Python's pickle to open and save a dictionary

In the final days of my intro comp sci class, we got to creating dictionaries. A homework program in our book asks us to create something that can look up, add, change, and delete a set of names and email addresses. It asks us to pickle the dictionary, but the kicker for me is that it stipulates that each time the program starts, it should retrieve the dictionary from the file and unpickle it. I don't know if I coded myself into a corner, but I can't figure out how to do this with what I've done so far.

My code:

import mMyUtils
import pickle
LOOK_UP = 1
ADD = 2
CHANGE = 3
DELETE = 4
QUIT = 5

def main():
    emails = {}
    choice = 0
    while choice != QUIT:
        choice = getMenuChoice()
        if choice == LOOK_UP:
            lookUp(emails)
        elif choice == ADD:
            add(emails)
        elif choice == CHANGE:
            change(emails)
        elif choice == DELETE:
            delete(emails)
        else:
            exit

def getMenuChoice():
    print()
    print('Name and Email Address Catalog')
    print('------------------------------')
    print('1. Look up an email address')
    print('2. Add a new email address')
    print('3. Change an email address')
    print('4. Delete an email address')
    print('5. Quit the program')
    print()

    choice = int(input('Enter the choice: '))
    while choice < LOOK_UP or choice > QUIT:
        choice = int(input('Enter a valid choice: '))

    return choice

def lookUp(emails):
    name = input('Enter a name: ')
    print(emails.get(name, 'Not found.'))

def add(emails):
    name = input('Enter a name: ')
    address = input('Enter an email address: ')
    if name not in emails:
        emails[name] = address
        pickle.dump(emails, open("emails.dat", "wb"))
    else:
        print('That entry already exists.')

def change(emails):
    name = input('Enter a name: ')
    if name in emails:
        address = input('Enter the new address: ')
        emails[name] = address
        pickle.dump(emails, open("emails.dat", "wb"))
    else:
        print('That name is not found.')

def delete(emails):
    name = input('Enter a name: ')
    if name in emails:
        del emails[name]
    else:
        print('That name is not found.')

main()

I know I should set my emails variable to be some form of pickle.load, but I can't figure it out for the life of me. mMyUtils is a library I made for try/except logic, I'll put that in once I get the new stuff working.

Upvotes: 2

Views: 8213

Answers (4)

okobaka
okobaka

Reputation: 616

Consider yourself using ast.literal_eval instead of pickle: http://docs.python.org/2/library/ast.html#ast.literal_eval

>>>import ast
>>> print mydict
{'bob': 1, 'danny': 3, 'alan': 2, 'carl': 40}
>>> string="{'bob': 1, 'danny': 3, 'alan': 2, 'carl': 40}"
>>> type(string)
<type 'str'>
>>> type( ast.literal_eval(string) )
<type 'dict'>

To save/read dict from file, you can do it like with normal string.

Upvotes: 1

Zachary Matthew Perry
Zachary Matthew Perry

Reputation: 53

The problem was, and I guess I didn't emphasis it enough, was what I was supposed to do if the dictionary didn't exist in the first place. The design doc states that you should load the dictionary every time you run the program. Well if you're running the program for the first time, you don't have a dictionary to load, leading to an error. I got around this by basically doing the function twice using try/except.

My code:

import mMyUtils
import pickle
import dictionaryGenerator
LOOK_UP = 1
ADD = 2
CHANGE = 3
DELETE = 4
QUIT = 5

def main():
    hasError = False
    try:
        emails = pickle.load(open('emails.dat', 'rb'))
        choice = 0
        while choice != QUIT:
            choice = getMenuChoice()
            if choice == LOOK_UP:
                lookUp(emails)
            elif choice == ADD:
                 add(emails)
            elif choice == CHANGE:
                change(emails)
            elif choice == DELETE:
                delete(emails)
            else:
                print("Good-bye!")
                exit
    except Exception as err:
        hasError = True
        mMyUtils.printError("Error: no such file",err)
        mMyUtils.writeToErrorLog()

    finally:
        if hasError:
            emails = {}
        choice = 0
        while choice != QUIT:
            choice = getMenuChoice()
            if choice == LOOK_UP:
                lookUp(emails)
            elif choice == ADD:
                add(emails)
            elif choice == CHANGE:
                change(emails)
            elif choice == DELETE:
                delete(emails)
            else:
                print("Good-bye!")
                exit





def getMenuChoice():
    print()
    print('Name and Email Address Catalog')
    print('------------------------------')
    print('1. Look up an email address')
    print('2. Add a new email address')
    print('3. Change an email address')
    print('4. Delete an email address')
    print('5. Quit the program')
    print()

    choice = int(input('Enter the choice: '))
    while choice < LOOK_UP or choice > QUIT:
        choice = int(input('Enter a valid choice: '))

    return choice

def lookUp(emails):

    name = input('Enter a name: ')
    print(emails.get(name, 'Not found.'))

def add(emails):
    name = input('Enter a name: ')
    address = input('Enter an email address: ')
    if name not in emails:
        emails[name] = address
        with open("emails.dat",  "wb") as infile:
            pickle.dump(emails, infile)

    else:
        print('That entry already exists.')

def change(emails):
    name = input('Enter a name: ')
    if name in emails:
        address = input('Enter the new address: ')
        emails[name] = address
        with open("emails.dat", "wb") as infile:
            pickle.dump(emails, infile)

    else:
        print('That name is not found.')

def delete(emails):
    name = input('Enter a name: ')
    if name in emails:
        del emails[name]
    else:
        print('That name is not found.')

main()

Upvotes: 0

Fabian
Fabian

Reputation: 4348

You must load the file and unpickle the data before you can access it, change lookUp() to this:

def lookUp(emails):
    with open("emails.dat", "rb") as fo:
        emails = pickle.load(fo)

    name = input('Enter a name: ')
    print(emails.get(name, 'Not found.'))

Upvotes: 1

NPE
NPE

Reputation: 500317

If you're saving the dictionary like so:

pickle.dump(emails, open('emails.dat', 'wb'))

The following will load it back:

emails = pickle.load(open('emails.dat', 'rb'))

Upvotes: 2

Related Questions