实践项目七:模拟银行转账系统(python+mysql)

最近学习python操作mysql数据库的知识,python访问数据库有自己的统一接口程序:Python DB API。这是我学习的一个小例子。(安装和基本知识可以自行复习:http://blog.csdn.net/xunalove/article/details/76695549)

环境

ubutu 16.04 + python2.7 + mysql 5.7.19

分析

首先要知道使用Python DB API 访问数据库的流程:
开始—->创建connection—->获取cursor—->执行查询, 执行命令, 获取数据, 处理数据—->关闭cursor —->关闭connection—->结束。

模拟银行转账系统的思路:(假设帐号1给账户2转账200元)

  • 第一步:首先需要检查帐号1和帐号2是否存在,
  • 第二步:满足条件下:接着检查帐号1是否有200元,
  • 第三步:满足条件下:帐号1减去200元,帐号2加上200元
  • 第四步:满足上面三步的条件下,将数据提交到数据库(提交事务)
    需要注意的是这四步任意一步出现一场,都要使用rollback回滚事务

创建mysql数据库

我使用的是命令行,当然你也可以使用可视化界面创建,看个人爱好。
我已经创建好了数据库为”test”
使用”use test”进入test数据库,创建数据表” accunt “

mysql> create table accunt(
    -> acctid int(11) not null primary key auto_increment,
    -> money int(11) not null);

创建两条信息

mysql> insert into accunt values('1','1000');
Query OK, 1 row affected (0.02 sec)

mysql> insert into accunt values('2','500');
Query OK, 1 row affected (0.02 sec)

使用select查看数据表如下

mysql> select * from accunt;
+--------+-------+
| acctid | money |
+--------+-------+
|      1 |   800 |
|      2 |   700 |
+--------+-------+
2 rows in set (0.00 sec)

代码实现

这里我们使用类的方法来实现功能,首先在脚本执行的入口处用到了argv来传入三个参数:付款人的id, 收款人的id ,转账的钱数。接着调用TransferMoney()类。这里主要有五个方法,先看检查id是否存在的实现:利用select语句从数据库中提取id==付款人的id,通过cursor.fetchall()提取所有数据保存在rs里面(此时是rs保存的是一个列表)列表长度为一则存在,判断金额是否大于200元方法类似。
下面就是执行转账(加减操作)的操作,用到了update方法,需要注意的是判断转账成功的这里用到了cursor.rowcount,它返回的值代表执行update之后数据库中改变的行数。
下面附上完整代码:

# -*- coding:utf-8 -*-

import sys
import MySQLdb

class TransferMoney(object):
    def __init__(self, conn):
    self.conn = conn
    def check_acct_available(self,acctid):
    try:
        cursor = self.conn.cursor()
        sql = "select * from accunt where acctid=%s"%acctid
        cursor.execute(sql)
        print "check_acct_available:" + sql
        rs = cursor.fetchall()
        if len(rs)!=1:
        raise Exception("帐号%s不存在"% acctid)
    finally:
            cursor.close()

    def has_enough_money(self,acctid, money):

        try:
        cursor = self.conn.cursor()
        sql = "select * from accunt where acctid=%s and money > %s"%(acctid,money)
        cursor.execute(sql)
        print "has_enough_money:" + sql
        rs = cursor.fetchall()
        if len(rs)!=1:
        raise Exception("帐号%s没有足够的钱"% acctid)
    finally:
            cursor.close()

    def reduce_money(self,acctid,money):
        try:
        cursor = self.conn.cursor()
        sql = "update accunt set money=money-%s where acctid=%s"%(money,acctid)
        cursor.execute(sql)
        print "reduce_money:" + sql

        if cursor.rowcount !=1: #使用rowcount是否影响数据库中的数据
        raise Exception("帐号%s减款失败"% acctid)
    finally:
            cursor.close()

    def add_money(self,acctid,money):
        try:
        cursor = self.conn.cursor()
        sql = "update accunt set money=money+%s where acctid=%s"%(money,acctid)
        cursor.execute(sql)
        print "add_money:" + sql

        if cursor.rowcount!=1:
        raise Exception("帐号%s加款失败"% acctid)
    finally:
            cursor.close()


    def transfer(self,source_acctid, target_acctid, money):
    try:
        #检查帐号是否可用
        self.check_acct_available(source_acctid)
        self.check_acct_available(target_acctid)

        #检查付款人是否有足够的money
        self.has_enough_money(source_acctid, money)

        self.reduce_money(source_acctid,money)
        self.add_money(target_acctid,money)
        self.conn.commit()
    except Exception as e:
        self.conn.rollback()
            raise e

#脚本执行的入口
if __name__=="__main__":
    source_acctid = sys.argv[1] #付款人的id
    target_acctid = sys.argv[2] #收款人的id
    money = sys.argv[3] #转账的金额

    conn = MySQLdb.Connect(host='127.0.0.1',user='root',passwd='root',db='test')

    tr_money = TransferMoney(conn)

    try:
    tr_money.transfer(source_acctid, target_acctid, money)
    except Exception as e:
        print "出现问题:" + str(e)
    finally:
        conn.close()

运行程序查看此时数据库的中数据的变化:
实践项目七:模拟银行转账系统(python+mysql)_第1张图片

总结:

在这里我们需要注意的是每次只需执行操作不论是否抛出异常都是关闭cursor,并且在数据库的最后需要关闭connection对象。其次就是commit的使用,假如我们update,insert,delet操作数据之后没有commit,则不会在数据库中改变数据,应为此时的数据只是作为一个事务,并没有提交和执行。最后就是roll back使用,在进行多操作时,其中一个操作抛出异常,就回滚,则前面进行的操作也是无效的,这里用到了事物的一致性,要么都操作,要么都不操作。。。
已经上传至github,链接:https://github.com/xuna123/Python_pro/tree/master/%E9%A1%B9%E7%9B%AE%E4%B8%83
参考资料:http://www.imooc.com/video/9219

你可能感兴趣的:(【Python】,【MySQL】,python学习小项目,python,mysql)