结合自动注册账号案例,详细剖析Python的pymysql模块使用(优化版)

1、引言

前面写过的一篇文章:【结合自动注册账号案例,详细剖析Python的pymysql模块使用】
里面的自动注册流程是第一版的,只能注册个人账号,后来需求有变更,新增了注册账号类型的选择,即注册流程有分【个人注册】和【企业注册】两种类型,不同的账号类型,在注册时,需要填写的参数有点区别,故需要对自动注册账号的脚本进行优化改造,下面将详细展开,同时也引申出在使用pymysql模块时遇到的问题及解决方案

2、需求分析

优化版本的注册功能,新增了注册账号类型的选择,整个自动化流程的顺序和关系如下图:

账号类型
个人账号
企业账号
手机号是否注册
发送验证码
更新手机号
查询验证码
注册
用户名是否注册
更新用户名

3、需求实现

完整代码如下:

import requests
import pymysql
import random

def auto_register(base_url, type, password=88888888, mobile=None, username=None):
    """连接数据库"""
    print ( '开始连接数据库...' )
    db = pymysql.connect (
        host='xxx.xxx.x.xx',
        port=3307,
        user='xxxxxx',
        passwd='xxxxxx',
        db='xxxxxx',
        autocommit=1  #PyMysql模块的连接对象默认是没有自动提交事务的,需要我们用一个commite()方法才能提交,此处添加autocommit = 1参数实现自动提交,就不用每次都commite()了
    )
    cur = db.cursor ()

    """【注册方式:1-个人账号、0-企业账号】"""
    if type == 1 or mobile != None:
        """【查询手机号】"""
        cur.execute ( "SELECT id FROM `wow_users` WHERE mobile = '{}'".format ( mobile ) )
        userdata = cur.fetchall ()
        if len ( userdata ) != 0:
            print ( '当前手机号已注册' )

            """【更新手机号】"""
            userid = userdata[0][0]
            print ( '当前用户id是:{}'.format ( userid ) )
            change_mobile = str ( mobile ) + '_' + str ( random.randint ( 1, 10000 ) )
            print ( '更新手机号为:{}'.format ( change_mobile ) )
            cur.execute ( "UPDATE `wow_users` SET `mobile`='{}' WHERE `id` = {}".format ( change_mobile, userid ) )
            print ( '更新手机号成功' )
        else:
            print ( '当前手机号未注册' )
            pass

        """【发送验证码】"""
        from_data1 = {'mobile': mobile, 'sId': 5}
        r1 = requests.post ( base_url + '/api/member/send-sms', data=from_data1 )
        if r1.status_code == 200:
            print ( '发送验证码成功' )
        else:
            print ( '发送验证码失败' )

        """【查询验证码】"""
        cur = db.cursor ()
        cur.execute("SELECT token FROM `wow_member_find` WHERE mobile = '{}' AND scenes = 5".format(mobile))
        finddata = cur.fetchall()
        code = finddata[0][0]
        print('验证码是:{}'.format(code))

        """【注册】"""
        from_data2 = {'is_personal': type, 'mobile': mobile, 'password0': password, 'password1': password, 'code': code}
        r2 = requests.post ( base_url + '/api/member/register', data=from_data2 )
        response = r2.json ()
        if response['message'] == 'ok':
            new_userid = response['data']['id']
            print ( '注册成功!新注册的用户id是:{}'.format ( new_userid ) )
        elif response['message'] == '手机验证码错误':
            print ( '手机验证码错误,注册失败!' )

    elif type == 0 or username != None:
        """【查询用户名】"""
        cur.execute ( "SELECT * FROM `wow_users` WHERE username = '{}'".format ( username ) )
        userdata = cur.fetchall ()
        if len ( userdata ) != 0:
            print ( '当前用户名已注册' )

            """【修改用户名】"""
            userid = userdata[0][0]
            print ( '当前用户id是:{}'.format ( userid ) )
            change_username = str (username) + '_' + str ( random.randint ( 1, 10000 ) )
            print ( '修改用户名为:{}'.format ( change_username ) )
            cur.execute ( "UPDATE `wow_users` SET username = '{}' WHERE id = '{}'".format ( change_username, userid ) )
            print ( '修改用户名成功' )
        else:
            print ( '当前用户名未注册' )
            pass

        """【注册】"""
        from_data3 = {'is_personal': 0, 'client_name': username, 'user_name': username, 'password0': password,
                      'password1': password}
        r3 = requests.post ( base_url + '/api/member/register', data=from_data3 )
        response = r3.json ()
        if response['message'] == 'ok':
            new_userid = response['data']['id']
            print ( '注册成功!新注册的用户id是:{}'.format ( new_userid ) )
        else:
            print ( '注册失败!' )

    """关闭游标和关闭数据库连接"""
    cur.close ()
    db.close ()
    print ( '关闭游标和数据库连接' )


if __name__ == '__main__':
    auto_register ( 'https://xxx', '1', mobile=13800000004 )

4、知识拓展

4.1、Python 函数形参

4.1.1、Python 函数形参类型

  • 必传参数:平时最常用的,也叫位置参数,必传确定数量的参数,传实参时位置要一一对应
  • 默认参数:在调用函数时可以传也可以不传,如果参数没有默认值,在调用时必需为其指定一个值;如果参数有默认值,在调用时值是可选的,如果为其提供了一个值,将会覆盖默认值
  • 可变参数:也称为不定长参数,就是传入的参数个数是可变的:*args,args是一个元组类型
  • 关键字参数:**kwargs,长度可变,但是需要以 key-value 形式传参

由于新的注册流程中,有分【个人注册】和【企业注册】,不同的账号类型传参会不一样,所以在此次优化版的脚本中,定义函数时,使用了python函数形参中的【默认参数】的传递方式:

def auto_register(base_url, type, password=88888888, mobile=None, username=None)

此处参数mobile和username就是默认参数,默认值设为None,这样后面在调用该函数,就可以根据注册账号类型,有选择性的传实参

更多相关知识可以参考【Python函数参数操作详解】

4.1.2、Python 函数形参顺序

位置参数>默认参数>可变参数>关键字参数

4.2、pymysql的事务操作函数

在前面写过的一篇文章:【结合自动注册账号案例,详细剖析Python的pymysql模块使用】中有提到:当执行的sql语句是增、删、改时,还需要使用commit()方法才能够真正的操作数据库,该方法即起到了提交事务的操作,但是在本次优化的代码中已经去掉了这个方法,而是在连接数据库db = pymysql.connect ()时,添加了autocommit=1的参数,实现了自动提交事务的操作。

之所以这样改进,是因为在没有添加autocommit=1的参数时,代码走到查询验证码那一步时,查询到的验证码却不是当前发送的最新的验证码,而是上一次的验证码,即pymysql读取不到后台数据库更新的数据!经过网上搜索,说原因在于:

  1. Mysql的存储引擎InooDB的事务隔离级别默认是 可重复读(Repeatable Read),例如A客户端事务未提交,而B客户端事务修改了数据,A客户端只能读取到小于等于当前事务版本号的数据(快照读),所以只有提交完事务后,开启新的事务中才能读取到新的数据。
  2. pymysql模块的连接对象默认是没有自动提交事务的,需要我们用一个commite()方法才能提交,不像我们在MySQL客户端中,每次select,update,delete都帮我们自动提交事务,所以只要我们手动提交了事务,再重新select就可以查到新的数据。

那么对应的解决方法:

  1. 每次在用游标对象执行完查询语句后都手动commite()提交
  2. 创建一个自动帮我们提交事务的连接对象,即连接数据库pymysql.connect ()时添加参数autocommit=1

下面是总结一下pymysql的事务操作函数

4.2.1、事务提交:commit()

如果没有设置自动提交,则每次操作后必须提交事务,否则操作无效。

4.2.2、事务回滚:rollback()

操作出错时,可以用这个函数回滚到执行事务之前
一般事务提交和事务回滚是结合着使用:

try:
    cur.execute(sql_1)
    cur.execute(sql_2)
    cur.execute(sql_3)
except Exception as e:
    db.rollback() # 事务回滚
    print('事务处理失败', e)
else:
    db.commit() # 事务提交
    print('事务处理成功', cur.rowcount)

4.2.3、自动提交事务:autocommit=True

用pymysql.connect()连接数据库时,连接对象默认是没有自动提交事务的,即autocommit=False,如果想实现自动提交事务,则应设置autocommit=True或autocommit=1。

db = pymysql.connect (
        host='xxx.xxx.x.xx',
        port=3307,
        user='xxxxxx',
        passwd='xxxxxx',
        db='xxxxxx',
        autocommit=1  # 实现自动提交事务
    )
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值