Hi again all,
I have been tussling with this program all day. I can't seem to get pickle.dumps (or f.write..tried that earlier) to save without saving over itself. If I do a deposit(option 1) and then a withdraw(option 2), and then history(option 3), it only shows the last option ran before history. I am trying to get it to save all transactions. I would also like it to pick up the account balance where it last was saved to file upon opening. I have no idea how to do that. I am running Python 2.7 on Windows 8. Save file is set to f=open('pettycash.txt', 'w'). See deposit lines 29-32 and withdraw lines 45-48: I use str() on the items to make them writeable to a list then make the lists then pickle.dump them to f. See history line 102 for the pickle.load.
Thank you.

    from datetime import date
    try:
        import cPickle as pickle
    except:
        import pickle
    import pprint

    now = date.today

    class Account:
        def __init__(self, initial):
            '''Retrieves account data.'''
            self.balance = initial
            print "User %s requested balance on %s: balance is $%s " % (user, now(),self.balance)
            print


        def deposit(self, amt):
            '''Deposit amount'''
            self.balance = self.balance + amt  # deposit adds to the balance
            print "User %s deposited %s amount on %s: balance is $%s " % (user, amt, now(),self.balance)
            print
            # convert to strings
            user1=str(user)
            amt1=str(amt)
            now1=str(now())
            selfbalance1=str(self.balance)
            #create list
            log=['Deposit','User :'+user1,' Amount :' +amt1,' Date :'+now1,' Balance :'+selfbalance1]
            f =open('pettycash.txt', 'wb')
            #dump list
            pickle.dump(log, f)

        def withdraw(self,amt):
            '''Withraw amount'''
            self.balance = self.balance - amt   # withdrawl subtracts from the balance
            print "User %s withdrew %s amount on %s: balance is $%s " % (user, amt, now(),self.balance)
            print
            # convert to strings
            user2=str(user)
            amt2=str(amt)
            now2=str(now())
            selfbalance2=str(self.balance)
            #create list
            log1=['Withdraw',' User :'+user2, ' Amount :'+amt2, ' Date :'+now2, ' Balance :'+selfbalance2]
            f =open('pettycash.txt', 'wb')
            #dump list
            pickle.dump(log1, f)

        def getbalance(self):
            '''Return account balance'''
            return self.balance
            print

    def printmenu():
        print "Please select an option from menu:"
        print 
        print "1 for Deposit"
        print "2 for Withdraw"
        print "3 for History"
        print "4 to Exit"
        print
        return input (">")

    def showbalance(now,self):
        print "Balance as of %s: is $%s " % (now(),self.balance)
        print

    def getnumberinput(txt):
        num = 0
        while num == 0:
            val = input(txt)
            num = float(val)
            if num <= 0:
                print "Please try again, your input has to be more than zero."
                num = 0
        return num
        print


    def pettycashdb(a):
        print "Welcome to the Petty Cash Tracker!"
        print
        choice = 0
        choice1 = 0
        log={}
        while choice <> 4:
            choice = printmenu()
            if choice == 1:
                #deposit
                deposit = getnumberinput("Deposit amount is:")
                a.deposit(deposit)

            elif choice == 2:
                # withdraw
                withdraw = getnumberinput("Withdraw amount is:")
                a.withdraw(withdraw)


            elif choice == 3:
                #history
                f=open('pettycash.txt', 'r')
                data=pickle.load(f)
                pprint.pprint(data)

            elif choice == 4:
                print
                print 'Thank you!'
                showbalance(now,a)
                f.close()
                print 'done'


    print'''
                          |===============================|
                          |Testing the petty cash database|
                          |===============================|
    '''
    user='default'
    a=Account(0.00)
    a.deposit(550.23)
    a.deposit(100)
    a.withdraw(650.23)
    print'''
                                |===============|
                                | Test complete |
                                |===============|
    '''

    if __name__ == '__main__':

        print "Please input your name for tracking: (example:'David Green')"
        print
        user= raw_input ("Please enter name:")
        print
        while user==0:
            user='default user'
        print 'Welcome, you are logged in as:', user
        print
        print "If you'd like to login as someone else, you need to relog"
        print
        relog=raw_input ("Would you like to close the application and relog? ")
        if relog=='y':
            print 'Exiting, please reopen application...'
            quit()
        else:
            print
            print "Balance as of %s:    $%s " % (now(),a.getbalance())
            print       

        foo = pettycashdb(a)
    else:
        print "Module petty cash tracker imported."  

Your menu function with returnig input fuction is quite nice. Your class definition seems to be wrong however as some mehods have not self as first parameter.

I can't seem to get pickle.dumps (or f.write..tried that earlier) to save without saving over itself.

     f =open('pettycash.txt', 'wb')

Instead of write mode, which creates a new file each time, open the file in append mode: see the example at Click Here where these lines are explained

def logError(msg):
   err = open("Errors.log","a")

How would I code how to read these databases in shelve? I'm trying to create a history menu to read the deposit database, the history database, and entire database(everything on f).

def store_deposit(db):
            transtype=('DEPOSIT')
            trans={}
            trans['  DEPOSIT IN AMOUNT OF  :']=amt
            trans['        BY USER         :']=user
            trans['        ON DATE         :']=now()
            trans['    NEW BALANCE IS      :']=self.balance
            db[transtype]=trans
        database=shelve.open('pettycash.dat')
        store_deposit(database)
        print
        print'Shelved DEPOSIT to pettycash.dat'
        print
        database.close()


def store_withdraw(db):
            transtype2=('WITHDRAW')
            trans2={}
            trans2[' WITHDRAW IN AMOUNT OF  :']=amt
            trans2['        BY USER         :']=user
            trans2['        ON DATE         :']=now()
            trans2['    NEW BALANCE IS      :']=self.balance
            db[transtype2]=trans2
        database2=shelve.open('pettycash.dat')
        store_withdraw(database2)
        print
        print 'Shelved WITHDRAW to pettycash.dat'
        print
        database2.close()

        #futher down in main menu if history is picked...
        elif choice == 3:
            #history
            choice1 = 0
            db = shelve.open("pettycash.dat", "r")
            #
            while choice<> 4:
                choice1=historymenu() #1 deposit, 2 withdraws, 3 entire, 4 exit
                if choice == 1:
                    depositDB=db[transtype]
                    deposits=depositDB.keys()
                    #????
                if choice ==2:
                    withdrawDB=db[transtype2]
                    withdraws=withdrawDB.keys()
                    #??????
                if choice==3:
                    #???

I don't know anything about shelve. This is a simple, cobbled together example that pickles a list of lists.

import pickle
import random

class Account:
    def __init__ (self):
        self.open_file()
        self.run_tests()

    def deposit(self, amt, comments=""):
        self.balance += amt
        self.data.append([self.balance, amt, 0, self.user, comments])
        print "depositing  %9.2f --> balance is now %9.2f" % (amt, self.balance)

    def exit_program(self):
        with open("./test_accounts.text", "w") as fp_out:
            pickle.dump(self.data, fp_out)

    def open_file(self):
        """ record layout = 
            [balance, amount_added, amount_withdrawn, user_id, comments]
        """
        with open("./test_accounts.text", "r") as fp:
            self.data = pickle.load(fp)
        latest_transaction = self.data[-1]
        self.balance = float(latest_transaction[0])
        print "testing open_file", self.balance, latest_transaction

    def print_all_recs(self):
        print "\n  Balance   Deposit  Withdraw       User  Comments"
        for rec in self.data:
            for ctr, fmt in enumerate(['%9.2f', '%9.2f', '%9.2f', '%10s', '%s']):
                print fmt % rec[ctr],
            print


    def run_tests(self):
        """ simulate transactions
        """
        self.user = 123
        for ctr in range(10):
            dollars = random.randint(1, 100)
            cents = random.randint(1, 99)
            amt = dollars + cents/100.0
            if ctr % 2:
                self.withdrawal(amt, str(ctr))
            else:
                self.deposit(amt, str(ctr))

        self.print_all_recs()

        ## simulate exit menu option
        self.exit_program()

    def withdrawal(self, amt, comments=""):
        if self.balance >= amt:
            self.balance -= amt
            self.data.append([self.balance, 0, amt, self.user, comments])
            print "withdrawing %9.2f --> balance is now %9.2f" % (amt, self.balance)
        else:
            print "\n%9.2f amount too large. You can only withdraw a maximum of %9.2f"\
                  % (amt, self.balance)

## initial balance
## do on first run only
initial=[[100.00, 0, 0, 999, "Initial balance"]]
fp=open("./test_accounts.text", "w")
pickle.dump(initial, fp) 
fp.close()

A=Account()

Edited 3 Years Ago by woooee

How do I call a deposit say from a menu below...tried self.deposit(amt), self is not recognized.

You can do it several ways. I would replace the run_tests function with a function that contains the menu and calls the other functions. The purpose of a class is to encapsulate everything in one object. So, you open the file once in the beginning, do all the transactions/menu within the class, and save/pickle the file at the end. One of the tutorials on classes Click Here.

Edited 3 Years Ago by woooee

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