[Tutor] how to create a persistent dictionary w/ cpickle?
Steven D'Aprano
steve at pearwood.info
Wed Sep 8 23:50:13 CEST 2010
On Thu, 9 Sep 2010 03:43:42 am Carter Danforth wrote:
> Hi, I'm trying to a create a basic addressbook for practice. I'm
> using a dictionary with cpickle, though I'm not sure how to
> persistently store each instance in the dictionary. Below is the code
> I have so far.
>
> If I run it once and add a contact and the details, it's fine.
> p.load(f) shows the details next time I run it, but if I add another
> contact, and run it again, the previous key:value doesn't show. It
> gets replaced by the new one.
Where do you think you are *adding* a new contact? You don't. You
*replace* the existing contact with a brand new one, every time.
The problem has nothing to do with pickle, or storing "each instance in
the dictionary". Pickle is already storing each instance in the
dictionary. The problem is that you never *add* anything to the address
book, you *replace* it each time, so there is never more than two
instances in the dictionary (one key, one value).
You don't have an address BOOK, you only have a single address.
> How can I fix this so that it adds the new key:value to the
> dictionary instead of replacing the existing one? Appreciate any
> help, thanks.
I would dump the entire address class for now and just go for something
nice and minimal. Get that working first, and then, *if necessary*,
wrap it in a class. This is Python, not Java -- we use whatever works,
and don't force everything to be a class when it doesn't have to be.
What's the simplest address record you might have? How about a name
linked to a telephone number and email?
address_book = {name: (tel, email), another_name: (tel, email), ...}
So, here's the basic algorithm:
(1) Look for the address-book. If it doesn't exist, create an empty
dictionary, and pickle it as the address-book.
(2) Read the address-book from the pickle file. It will be a dictionary,
possibly empty.
(3) Add an address to the dictionary. Don't create a new dictionary:
>>> addresses = {} # creates a new, empty address book
>>> addresses["Fred"] = ("1234 5678", "fred at example.com")
>>> addresses["Betty"] = ("2468 1357", "betty at nowhere.com")
>>> addresses # not empty any more
{'Betty': ('2468 1357', 'betty at nowhere.com'), 'Fred': ('1234
5678', 'fred at example.com')}
(3) Save the dictionary to the pickle file.
Once you have those steps happening manually, then wrap it into a class
so they happen automatically.
Some more comments on your code:
> import cPickle as p
Now that's just lazy. While laziness in a programmer in a good thing,
this is taking it to extremes!!! You use pickle twice, three times if
you count the import. Is it really such a burden on you to
type "cPickle" (or "pickle") two more times, that you need to rename
it "p"?
Excessive use of one-character names is one of the worst programming
habits you can have. Don't do this.
> addressbook = 'addressbook.data'
Misleading variable name. "addressbook" isn't an addressbook at all,
it's a filename.
> f = file(addressbook, 'r+')
You shouldn't keep the file open for large periods of time. On Windows,
it may mean that it will be locked from any other program accessing it
during that time, and it risks data corruption if your program crashes
or the power goes out.
Open and close the file just when you need it.
> class address:
A minor point: it is the convention in Python that (most) classes start
with a capital letter. So Address would be the class, leaving address
available for an instance of the class:
address = Address()
> def __init__(self, name, tel, email):
> self.name = name
> self.tel = tel
> self.email = email
> ab = {self.name : self.tel}
> f = file(addressbook, 'r+')
> p.dump(ab, f)
>
> print p.load(f)
> x = raw_input()
>
> if x == 'add':
> name = raw_input('\nName: ')
To get a blank line before the prompt, it might be nicer to do this:
print
name = raw_input('Name: ')
That's a matter of personal preference though.
> tel = raw_input('Tel: ')
> email = raw_input('Email: ')
> contact = address(name, tel, email)
Hope this helps,
--
Steven D'Aprano
More information about the Tutor
mailing list