Python--银行转账系统的简单实现

银行转账时,本质就是对数据库中的数据进行加减法,但是当我们在转账的中途突然断电了怎么办,这里就需要用到数据库的执行事务。

        事务机制可以保证数据的一致性。

        失误应该具有4个属性:原子性、一致性、隔离性、持久性。这四个数次那个通常称为ACID特性。

        *原子性(atomicity)。一个事物是一个可分割的工作单位,事物中包括的诸操作要么都做,要么都不做。

        *一致性(consistency)。事物必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。

        *隔离性(isolation)。一个事物的执行不能被其他事物干扰。即一个事物内部的操作及使用的数据对并发的其他事物是隔

            离的,并发执行的各个事物之间不能相互干扰

        *持久性(durability)。持续性也称为持久性,只一个事务一旦提交,他对数据库中数据的改变就应该是永久性的。接下来

           的其他操作或故障不应该对其有任何影响。

Python DB API 2.0 的事务提供了两个方法 commit 或 rollback。

        对于支持事务的数据库, 在Python数据库编程中,当游标建立之时,就自动开始了一个隐形的数据库事务。commit()方法游标的所有更新操作,rollback()方法回滚当前游标的所有操作。每一个方法都开始了一个新的事务。

import sys
import pymysql


class TransferMoney(object):
    def __init__(self, conn):
        self.conn = conn

    def transfer(self, source_acctid, target_acctid, money):
        """转账函数"""
        try:
            # 判断账户是否存在?
            self.check_acct_available(source_acctid)
            self.check_acct_available(target_acctid)
            self.has_enough_money(source_acctid, money)
            # 001: 1000   002: 500
            # 001: 1000    002: 500
            self.reduce_money(source_acctid, money)
            self.add_money(target_acctid, money)
            self.conn.commit()
        except Exception as e:
            # 撤销数据库的执行
            self.conn.rollback()
            raise e

    def check_acct_available(self, acctid):
        """检测账户是否存在?"""
        cur = self.conn.cursor()
        try:
            # 查询账户名为acctid的详细信息
            select_sql = 'select * from account where accid=%s;' % (acctid)
            cur.execute(select_sql)
            print("execute sql:%s" % (select_sql))

            res = cur.fetchall()
            if len(res) != 1:
                raise Exception("帐号%s不存在" % (acctid))
        finally:
            cur.close()

    def has_enough_money(self, acctid, money):
        """检测账户是否有足够的钱"""
        cur = self.conn.cursor()
        try:
            select_sql = 'select money from account where accid=%s' \
                         %(acctid)
            cur.execute(select_sql)
            print('has_enough_money sql: %s' %(select_sql))
            res = cur.fetchall()
            if res:

                now_money = int(res[0][0])
                if int(now_money) < int(money):
                    raise  Exception("账户%s没有足够的钱,目前金额为 %d" %(acctid, now_money))
        finally:
            cur.close()
    def reduce_money(self, acctid, money):
        """给其他账户进行转账操作"""
        cur = conn.cursor()
        try:
            update_sqli = 'update account set money=money-%s where accid=%s' %(money, acctid)
            cur.execute(update_sqli)
            print('reduce_money sql:%s' %(update_sqli))
        except Exception as e:
            print("reduce money failed:",e)
        finally:
            cur.close()

    def add_money(self, acctid, money):

        cur = conn.cursor()
        try:
            update_sqli = 'update account set money=money+%s where accid=%s' % (money, acctid)
            cur.execute(update_sqli)
            print('add_money sql:%s' % (update_sqli))
        except Exception as e:
            print("add money failed:",e)
        finally:
            cur.close()



if __name__ == "__main__":
    conn = pymysql.connect(
        host='localhost', user='root', passwd='yutao',
        db='yutao', charset='utf8')

    

    # sys.argv 变量存储[脚本名, 传递的第一个参数,传递的第2个参数, ]
    source_acctid = sys.argv[1]
    target_acctid = sys.argv[2]
    money = sys.argv[3]


    trans_money = TransferMoney(conn)
    try:
        trans_money.transfer(source_acctid, target_acctid, money)
    except Exception as e:
        print("转账出现问题:", e)
    finally:
        conn.close()

猜你喜欢

转载自blog.csdn.net/biu_biu_0329/article/details/80613743