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."  

Recommended Answers

All 6 Replies

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()

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.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.