Hello, I am fairly new to Python and starting to get it. But I am having some difficulty with pickle. I am trying to get a account program to pickle user input and to save that in a data file and then reload said info and read as input for the program. I have finally got the pickle portion down, I am able to send the info I want but I cannot figure out the correct syntax to be able to keep adding to the file instead of simply overwriting what is in the data file. I want to be able to pickle info into set keys I guess, so that I can recall certain portions, vice versa. I am assuming it should be a list with a counter, that will keep adding to the file but not sure how to accomplish that. The code is below. I would appreciate any help. This is homework, but I am not trying to get anyone to just do it. I would really like to find out how to do this.

I have tried finding examples online but cannot find any code that does not totally confuse me but that also contains what I am trying to accomplish in it.

Thanks for any help!!!

import pickle as p

acctHist = 'acctHist.data'

class pettyAccount:
    def __init__(self, initial, open='05 Sep 07'):
        self.balance = initial
        openDate = open
    def deposit(self, amt, dDate='30 Oct 07'):
        self.balance = self.balance + amt
        self.date = dDate
    def withdraw(self, amt, wDate='30 Oct 07'):
        self.balance = self.balance - amt
        self.date = wDate
    def getbalance(self, gDate='30 Oct 07'):
        self.date = gDate
        return self.balance
        
    def welcome(self):
        prompt = input ('Welcome to the petty cash account: \
                        Enter 1 to Record a Deposit \
                        Enter 2 to Record a Withdrawal \
                        Enter 3 to Get the Balance')
        if prompt == 1:
            newDep = input ('Amount of deposit:')
            newDate = raw_input ('Date of deposit:')
            a.deposit(newDep)
            f = file(acctHist, 'w')
            pickFile = 'Deposit:',newDep, newDate
            p.dump(pickFile, f)
            f.close()
            g = file(acctHist)
            dTest = p.load(g) # A test so I could make sure that pickle was working
            print dTest
            print
            print 'The new balance is $',a.getbalance(), 'on %s.' % newDate
            return a.welcome()
        elif prompt == 2:
            newWith = input ('Amount of withdrawal:')
            balance = a.getbalance()
            if newWith > balance:
                print 'Withdrawal exceeded account balance: $',balance, ' Reduce withdrawal amount.'
                return a.welcome()
            else:
                newDate = raw_input ('Date of withdrawal:')
                a.withdraw(newWith)
                f = file(acctHist, 'w')
                pickFile = 'Withdrawl:',newWith, newDate
                p.dump(pickFile, f)
                f.close()
                g = file(acctHist)
                wTest = p.load(g)
                print wTest # A test so I could make sure that pickle was working
                print
                print 'The new balance is $',a.getbalance(), 'on %s.' % newDate
                return a.welcome()
        elif prompt == 3:
            today = raw_input ("Enter today's date:")
            print 'The current balance is $',a.getbalance(), 'on %s.' % today
            return a.welcome()
        else:
            print 'Thank you, goodbye'

a = pettyAccount(1000)
a.welcome()

Is there a better way for me to accomplish my goal? As in write the info to a file and not use pickle. Any help is appreciated, even a suggestion for a different way to give me a new search term to help me find a new angle.

Hi sidbizzle,

So if I am understanding your code correctly, you are trying to set up a program that prints a welcome prompt with a menu, then allows the user to deposit or withdraw from an account. The amount of money in the account is stored in acctHist.data, along with the date of the last transaction. Yes?

Problem #1: the account object 'a' always begins with 1000. Shouldn't it begin with whatever is in acctHist.data? In other words, the first time you create the account it should contain 1000, but every time the program is executed after that it ought to read acctHist.data and get the amount, then add to or subtract from that amount.

Problem #2: does the acctHist.data file store the account or the transaction history for the account? Because the name of the file and the way you describe it make it sound like it's a transaction history, but your code makes it look like just a raw deposit of the amount of money currently in the account + the last transaction date.

If you would like to make acctHist.data a transaction history, may I make a recommendation? Rather than pickling individual tuples of ('Transaction Type:',newAmt, newDate), create a dictionary of transactions and pickle that, instead. Dictionaries are primitive data structures which contain key-value pairs. So what you'd want to do is something like this:

transactions = dict()
transactions['TRANSACTION_ID'] = ('Transaction Type:', newAmt, newDate)
pickle.dump(transactions, f)

It might be smarter to simply make this transaction dictionary an instance variable of the pettyAccount class, then pickle the whole pettyAccount object!

Hope this helps.

I'm sure that this a major Newbie question... but looking the code that you 2 have posted I am still WAY lost. I have been working on it for hours and hours and have flipped back and forth from a dictionary to using a list... I am so lost in the code that I have typed right now that I don't know which way is up.
I'll attach what I have (plz be kind as I know it's a complete mess), and if you can point me in the right direction that would be GREAT!!! (also... could you please dumb it down as much as possible for me?)
Thanks in advance!

import pickle as p
import operator

class pettyAccount():
    def __init__(self, initial=0,date='13 June 08'):
        self.balance = initial
        self.id= id
        self.date= date
        
    def deposit(self, amt):
        self.balance = self.balance + amt
        return self.balance
    def withdraw(self, amt):
        self.balance = self.balance - amt
        return self.balance
    def getbalance(self):
        f = open(acctHist, 'r')
        account_list=p.load(f)
        f.close()
        return (account_list)
    
        
def welcome(self):
    #print account_list[1:0]
    prompt = 0
    while prompt < 4: 
        print ('Welcome to the petty cash account: \n\n\
            Enter 1 to Record a Deposit \n\
            Enter 2 to Record a Withdrawal \n\
            Enter 3 to Get the Balance\n\
            Enter 4 to Exit\n ')
        prompt=input('Enter option: ')
        
        if prompt == 1:
            newDep = input ('Amount of deposit: ')
            newDate = raw_input ('Date of deposit: ')
            newid=input('Enter a ID number for this transaction')
            newAmt=a.deposit(newDep)
            depList=dict (a=newAmt, b=newDate, c= newid)             # Makeing the deposit List
            if id in id_list:
                print "This id already exists, try again!"
            else:
                id_list.append(id)
                break
            #depList[newid]=('Deposit: ', newAmt, newDate)
            #depList.append((newAmt, newDate, newid))                  #Putting the List together   
            f = open(acctHist, 'w')
            p.dump(depList,f)                                                             #Dumping the List
            #p.dump(a.deposit(newDep), f)
            #p.dump(newDate,f)
            f.close()
            
            print '--------------------------------------------------------'
            print 'The new balance is $ %s on .' % newAmt, newDate
            #print 'The new balance is $',a.getbalance(), 'on %s.' % newDate
            print '--------------------------------------------------------\n'
            
        
        elif prompt == 2:
            newWith = input ('Amount of withdrawal: ')
            balance = a.getbalance()
            if newWith > balance:
                print '--------------------------------------------------------'
                print 'Withdrawal exceeded account balance: $',balance, ' \nReduce withdrawal amount.'
                print '--------------------------------------------------------\n'
                
            else:
                newDate = raw_input ('Date of withdrawal: ')
                f = file(acctHist, 'w')
                p.dump(a.withdraw(newWith), f)
                p.dump(newDate,f)
                f.close()
                print '--------------------------------------------------------'
                print 'The new balance is $',a.getbalance(), 'on %s.' % newDate
                print '--------------------------------------------------------\n'
              
        elif prompt == 3:
            
            newAmt= account_list['a']
            print '--------------------------------------------------------'
            print 'The current balance is $ %s' %newAmt
            print '--------------------------------------------------------\n'
            
        
        else:
             print 'Thank you, goodbye'


a=pettyAccount()
acctHist = 'acctHist.data'
try:
    fin = open(acctHist, "r")
    account_list = p.load(fin)
    fin.close()
    print "Account database file %s has been loaded!" % acctHist
    print account_list
    welcome(account_list)
except IOError:
    print "Cannot find account database file %s" % acctHist
    welcome(0)

ps. I know that the program doesn't work right now... the major problem that I am having is trying to get the correct input from the file (and vice-versa) so that I can update it with a new entry.
If you have more questions about what I am trying to do PLEASE don't hesitate to ask!

Hi count_chockula,

First of all, class definitions do not have parentheses after them. So:

class pettyAccount():

should be:

class pettyAccount:

Second of all, why are you asking the user for the date and time? Python can calculate that for you. See the datetime module. A good rule of thumb in design is, don't make the user do more than the minimum necessary amount of work. If you go to an ATM, does it force you to enter the date? Or an ID? Of course not; it calculates these things for you.

So by that reasoning, you should also have the program make its own IDs. If you don't feel like doing a whole lot of work, the ID could just be a timestamp from the datetime module. Or you could just keep a running counter - one, two, three, and so on.

Third of all, what is "id_list" supposed to be? You never create it - you only append to it - so the program craps out with an "id_list not defined" message. Maybe you should make this a field of the pettyAccount object?

Hope this helps.

Thanks for getting back with me. I have fixed the pettyAccount thing... not real sure why I left it in there to begin with.
As for the time stamp... I was going to work on getting the time mod. in there later. I was just trying to get the "date" to save in the file to begin with. I would love to put just the time stamp in there and use that as an "id" string, but I'm having trouble saving the information every time that I add or subtract something. I can get it to save... but every time that I add something it just updates the file... that is, it doesn't add to the file.
What's more, I can't seem to read the information back from the file so that if I need to change just 1 of the entries all I would have to do is put in the correct "id" in and edit it.
(This above is where I need the help)
If you could help me out I would GREATLY apprish!

Hi count_chockula,

The file is being overwritten because your file handles are created with an option of "w" which is short for "write." To add extra data to a file without overwriting, you need an option of "a" which is short for "append."

If you use pickle.dump() with an appending file handle, it will add objects to the file as if the file were a queue. Doing pickle.load() on a file like that will cause the objects to be popped one at a time, in FIFO order. This is generally how pickle works.

My suggestion to you is this. Don't write to the file every time you perform a transaction. If I was writing this program, I would stick only one object inside the text file - a dictionary containing all transactions, keyed by their IDs. I would load the dictionary when the program begins, before the user makes any choices. Then I would alter the dictionary whenever the user does something. Then I would re-pickle it when the program ends. That way, you only need to worry about reading and writing once - at the beginning and the end of the program, respectively.

Hope this helps.

Thanks for that quick responce!!! I knew that it had to be a reason for my mess up's in the Pickle.
I like where you are going with the dictionary... and I can build the dictionary with the 'date' stamp as the key. But, what I don't know how to do is add the next key:val everytime that I add something (you can't append a dictionary...right?). Also... how does one 'add' to the total if you are putting a new value with a new key.
In other words... this is what I get when I call the dictionary back in... {'16 Jun 2008 01:41:17': ('Deposit: ', 6, '3')} With my current code...

import pickle as p
import sys
import time

class pettyAccount:
    def __init__(self, initial=0,date='13 June 08'):
        self.balance = initial
        self.id= id
        self.date= date
        
    def deposit(self, amt):
        self.balance = self.balance + amt
        return self.balance
    def withdraw(self, amt):
        self.balance = self.balance - amt
        return self.balance
    def getbalance(self):
        f = open(acctHist, 'r')
        account_list=p.load(f)
        f.close()
        return account_list
    
        
def welcome(self):
    prompt = 0
    while prompt < 4: 
        print ('Welcome to the petty cash account: \n\n\
            Enter 1 to Record a Deposit \n\
            Enter 2 to Record a Withdrawal \n\
            Enter 3 to Get the Balance\n\
            Enter 4 to Exit\n ')
        prompt=input('Enter option: ')
        
        if prompt == 1:
            newDep = input ('Amount of deposit: ')
            newDate = raw_input ('Date of deposit: ')
            newid=input('Enter a ID number for this transaction')
            newAmt=a.deposit(newDep)
            depList={}
            depList[time.strftime('%d %b %Y %H:%M:%S')]=('Deposit: ', newAmt, newDate)
            f = open(acctHist, 'w')
            p.dump(depList,f)                                                             #Dumping the List
            f.close()
            
            print '--------------------------------------------------------'
            print 'The new balance is $ %s on .' % newAmt, newDate
            
            print '--------------------------------------------------------\n'
            
        
        elif prompt == 2:
            newWith = input ('Amount of withdrawal: ')
            balance = a.getbalance()
            if newWith > balance:
                print '--------------------------------------------------------'
                print 'Withdrawal exceeded account balance: $',balance, ' \nReduce withdrawal amount.'
                print '--------------------------------------------------------\n'
                
            else:
                newDate = raw_input ('Date of withdrawal: ')
                f = file(acctHist, 'w')
                p.dump(a.withdraw(newWith), f)
                p.dump(newDate,f)
                f.close()
                print '--------------------------------------------------------'
                print 'The new balance is $',a.getbalance(), 'on %s.' % newDate
                print '--------------------------------------------------------\n'
              
        elif prompt == 3:
            print account_list
            newAmt= account_list[:1]
            print '--------------------------------------------------------'
            print 'The current balance is $ %s' %newAmt
            print '--------------------------------------------------------\n'
            
        
        else:
             print 'Thank you, goodbye'


a=pettyAccount()
acctHist = 'acctHist.data'
try:
    fin = open(acctHist, "r")
    account_list = p.load(fin)
    fin.close()
    print "Account database file %s has been loaded!" % acctHist
    print account_list
    welcome(account_list)
except IOError:
    print "Cannot find account database file %s" % acctHist
    welcome(0)

How do I 'add' a new deposit to the total now?
Thanks for being so understanding with me... I know it must be hard!

Um just a quick note:
Im under the impression you do have parentheses after a class definition becuase this can be used to set class parents and attibutes as well as making it a new-style class.

# a few examples
import wx

class MainFrame(wx.Frame):
    pass
    #this means this class has all the attributes of wx.Frame
class Parent(object):
    #new style class
class Child(Parent):
    #child has all attributes of Parent

Hi count_chockula,

You can indeed edit a dictionary. You would load the dictionary with pickle.load(), then add a new key-value pair, then dump it again, like so:

f = open("filename.txt", "r")
d = pickle.load(f)
f.close()
d["new_key"] = "new_value"
f = open("filename.txt", "w")
pickle.dump(d, f)
f.close()

Now filename.txt contains the same pickled dictionary from before, but with an addition.

This article has been dead for over six months. Start a new discussion instead.