基于Python實現(xiàn)一個簡單的銀行轉(zhuǎn)賬操作
前言
在進行一個應用系統(tǒng)的開發(fā)過程中,從上到下一般需要四個構(gòu)件:客戶端-業(yè)務邏輯層-數(shù)據(jù)訪問層-數(shù)據(jù)庫,其中數(shù)據(jù)訪問層是一個底層、核心的技術。而且在實際開發(fā)中,數(shù)據(jù)庫的操作也就是說數(shù)據(jù)訪問層都是嵌套在其他語言中的,其是編程的核心。本文面向的是python語言,即通過python操作數(shù)據(jù)庫來實現(xiàn)簡單的銀行轉(zhuǎn)賬操作。
工具
python提供了python DB API用來統(tǒng)一操作數(shù)據(jù)庫,使訪問數(shù)據(jù)庫的接口規(guī)范化,在沒有python DB API之前,接口程序十分混亂,不同的數(shù)據(jù)庫需要不同的操作接口,所以這個接口提供了極大的方便。在具體操作的時候,我們需要操作數(shù)據(jù)庫以及其他邏輯的python代碼,數(shù)據(jù)庫連接對象connection來建立連接,數(shù)據(jù)庫交互對象cursor來“運送”數(shù)據(jù),一個健壯的系統(tǒng)必不可少的便是數(shù)據(jù)庫異常類Exceptions。整個訪問數(shù)據(jù)庫流程如下圖:
接下來分別介紹下兩個主要對象:
connection:數(shù)據(jù)庫連接對象,建立python客戶端與數(shù)據(jù)庫的網(wǎng)絡連接。
創(chuàng)建方法:MySQLdb.connect(),包括的主要成員方法:
cursor():使用該連接創(chuàng)建并返回游標
commit():提交當前事務
rollback():回滾當前事務
close()關閉連接
cursor:游標對象,用于執(zhí)行查詢與獲取結(jié)果,cursor對象支持的主要方法如下:
execute():執(zhí)行SQL語句,將結(jié)果從數(shù)據(jù)庫獲取到客戶端
fetchone():取得結(jié)果集的下一行
fetchmany(size):獲取結(jié)果集的下size行
fetchall():獲取結(jié)果集中剩下的所有行
rowcount:最近一次execute返回數(shù)據(jù)的行數(shù)
close():關閉游標對象
在上面的方法中提到了一個關鍵名詞:事務,什么是事務呢?他是訪問和更新數(shù)據(jù)的一個程序執(zhí)行單元,很多操作的一個集合,有四個特點:
原子性:事物中包括的諸操作要么都做,要么都不做
一致性:事務必須使數(shù)據(jù)庫從一致性狀態(tài)變到另一個一致性狀態(tài)
隔離型:一個事務的執(zhí)行不被其他事務干擾
持久性:事務一旦提交,它對數(shù)據(jù)庫的改變就是持久性的
事務的上述特點正是我們完成銀行轉(zhuǎn)賬操作的關鍵。
具體實現(xiàn)
在開發(fā)中我們怎么樣使用事務呢?
關閉自動commit()
正常結(jié)束事務:conn.commit(),
異常結(jié)束事務:conn.rollback()
在銀行轉(zhuǎn)賬系統(tǒng)中,需要考慮如下需求:比如A給B轉(zhuǎn)賬,當A賬戶上減少了M錢時,必須在B賬戶上多了M錢,不能A減了B沒加,也不能B加了A還沒有減,當然賬戶必須是有效的,M錢的金額肯定要大于A賬戶上的金額。所以在具體設計的時候,需要將A賬戶的金錢減少和B賬戶的金錢增加作為一個事務,要么同時成功,要么一起失敗。按照這個需求,書寫代碼,詳細代碼見github,代碼復制和數(shù)據(jù)庫如下,有兩個賬戶,分別擁有金錢110和10,在運行代碼的時候在參數(shù)欄輸入1,2,100(source_acctid, target_acctid, tranfer_money)。
整個代碼的邏輯如下:首先連接數(shù)據(jù)庫,之后執(zhí)行邏輯,然后斷開數(shù)據(jù)庫連接,執(zhí)行的邏輯包括檢查轉(zhuǎn)賬雙方的賬戶是否有效,轉(zhuǎn)賬金額是否多于轉(zhuǎn)賬人的賬戶余額,分別給轉(zhuǎn)賬雙方的帳號金額發(fā)生變化。如果正常結(jié)束事務,提交修改數(shù)據(jù)庫,否則回滾。
#coding:utf-8 import sys import MySQLdb class TransferMoney(): def __init__(self, conn): self.conn = conn def transfer(self, src, target, money): try: self.check_acct_available(src) self.check_acct_available(target) self.has_enough_money(src, money) self.reduce_money(src, money) self.add_money(target, money) self.conn.commit() except Exception as e: print e self.conn.rollback() def reduce_money(self, src, money): cursor = self.conn.cursor() try: sql = "update account set money = money - %s where acctid = %s" %(money, src) cursor.execute(sql) print "reduce_money: " + sql #rs = cursor.fetchall() if cursor.rowcount != 1: raise Exception("the account reduce money fail") finally: cursor.close() def add_money(self, target, money): cursor = self.conn.cursor() try: sql = "update account set money = money + %s where acctid = %s" %(money, target) cursor.execute(sql) print "add_money: " + sql #rs = cursor.fetchall() if cursor.rowcount != 1: raise Exception("the account add money fail") finally: cursor.close() def check_acct_available(self, accit): cursor = self.conn.cursor() try: sql = "select * from account where acctid = %s" %accit cursor.execute(sql) print "check_acct_available: " + sql rs = cursor.fetchall() if len(rs) != 1: raise Exception("the account %s is not exist" %accit) finally: cursor.close() def has_enough_money(self, src, money): cursor = self.conn.cursor() try: sql = "select * from account where acctid = %s and money >= %s " %(src, money) cursor.execute(sql) print "has_enough_money: " + sql rs = cursor.fetchall() if len(rs) != 1: raise Exception("the account does not have enough money") finally: cursor.close() if __name__ == "__main__": source_acctid = sys.argv[1] target_acctid = sys.argv[2] money = sys.argv[3] conn = MySQLdb.connect( host = "127.0.0.1", user = '******', passwd = '******', port = 3306, db = '******' ) tr_money = TransferMoney(conn) try: tr_money.transfer(source_acctid, target_acctid, money) except Exception as e: print e finally: conn.close()
總結(jié)
通過對數(shù)據(jù)庫的操作就可以實現(xiàn)一個簡單的銀行轉(zhuǎn)賬系統(tǒng),所以在系統(tǒng)開發(fā)的時候,我們應該盡最大的可能,讓整個系統(tǒng)不只是多個組件的拼接,應該實現(xiàn)1+1>2。
相關文章
python正則表達式中匹配次數(shù)與貪心問題詳解(+??*)
正則表達式是一個特殊的字符序列,它能幫助你方便的檢查一個字符串是否與某種模式匹配,下面這篇文章主要給大家介紹了關于python正則表達式中匹配次數(shù)與貪心問題(+??*)的相關資料,需要的朋友可以參考下2022-10-10Python實現(xiàn)構(gòu)建一個儀表板的示例代碼
這篇文章主要為大家詳細介紹了Python如何實現(xiàn)構(gòu)建一個儀表板,文中的示例代碼講解詳細,具有一定的參考價值,感興趣的小伙伴可以了解一下2023-03-03Python切換pip源兩種方法(解決pip?install慢)
這篇文章主要給大家介紹了關于Python切換pip源兩種方法(解決pip?install慢),我總結(jié)的這幾種更換pip源的常用方式,希望可以幫助您成功配置國內(nèi)源,解決安裝Python包速度慢的問題,需要的朋友可以參考下2023-11-11