mysql过程 设置 Python3_[接口测试-实战]01 python3操作mysql

本文记录了使用 Python3 和 pymysql 模块操作 MySQL 的实战过程,包括数据库操作封装、日志记录和单例模式应用。通过示例代码展示了如何处理 SQL 注入问题和日志设置,以及在遇到错误时如何定位问题。
摘要由CSDN通过智能技术生成

前言

最近跟大婶的一个课程(可以到千聊平台搜索“颠覆你的python接口自动化测试”),主要讲通过py+httplib+mysql+Django来搭建接口测试的一个实战,课程使用的是环境和我的环境有点区别,课程使用的是py2+httplib,而我使用的是py3+requests。主要跟的其实还是思想,而且我也收获良多,这里我会将学习的结果输出到简书,供应大家一起学习,当然我自认为写代码的能力和经验有限,所以可能会出一些低级的问题,希望各位指点,我们一起学习,进步。

这里我记录一下,我在跟第四节课《python操作mysql》的成果记录以及遇到的一些坑。

文章目录

课程内容简介

实践代码

课程内容简介

大婶的第四次分享《python操作mysql》主要包括三个内容,“py操作mysql实例”,“本章涉及的语法讲解”,“pycharm使用基础”,本文的主要内容还是“py操作mysql实例”,其他的部分,在后面的文章中陆续更新。

那么下面我们对实例部分做一个简单的介绍,课程主要对mysqldb进行一个简单再封装的操作,提供几个框架中会用到的一些基本功能,功能比较简单(代码中有注释),而mysqldb暂时不支持py3,所以实战中我使用的是pymysql这个模块。(不要问我为什么知道,我不告诉你)

实战代码

实战涉及到的新知识(这里只是记录一些关键字,后面会有相关的文章输出):logging模块,pymysql模块,单例设置模式

实战中我封装了两个文件,opmysql.py(数据库操作的封装),mylogging.py(logging日志的封装)

在看代码之前,我先抛出几个问题,大家可以带着这些问题看代码,印象可能会更深刻,当然很多问题都可以在代码中找到答案,毕竟,我还是很喜欢写注释的。

课程中每次使用logging的时候都需要设置输出格式信息,怎么封装

希望整个系统公用一个logging实例,怎么做

除了捕获到Exception的时候需要输入log,还有什么时候需要输出log,才能帮助我在出现bug的时候定位问题

凡是有sql的地方都有sql注入的问题,所以,在封装的过程中,我们该怎么处理sql注入的问题

# mylogging.py

#!/usr/bin/env python3

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

import logging

#在实际开发中,不会直接用logging,一般会将logging封装一下,再用

class MyLogging:

'''

logging的初始化操作,以类封装的形式进行

'''

def __init__(self):

filename = "app.log" #日志文件的地址

self.logger = logging.getLogger() #定义对应的程序模块名name,默认为root

self.logger.setLevel(logging.INFO) #必须设置,这里如果不显示设置,默认过滤掉warning之前的所有级别的信息

sh = logging.StreamHandler() #日志输出到屏幕控制台

sh.setLevel(logging.ERROR) #设置日志等级

fh = logging.FileHandler(filename=filename) #向文件filename输出日志信息

fh.setLevel(logging.INFO) #设置日志等级

# 设置格式对象

formatter = logging.Formatter("%(asctime)s %(filename)s[line:%(lineno)d]%(levelname)s - %(message)s") #定义日志输出格式

# 设置handler的格式对象

sh.setFormatter(formatter)

fh.setFormatter(formatter)

# 将handler增加到logger中

self.logger.addHandler(sh)

self.logger.addHandler(fh)

# python的模块是天然的单例模式,因为模块在第一次导入的时候,会生成.pyc文件,当第二次导入时,就会直接加载.pyc文件,而不会再次执行模块代码

# 因此,我们只需要把相关的文件和数据定义在一个模块中,就可以获得一个单例对象了

# 日志操作对象logger,这里设置为单例,则凡是需要使用logging对象的地方都共同这个logger,节省内存开销

mylogger = MyLogging().logger

if __name__=="__main__":

#test

mylogger.debug("debug")

mylogger.info("info")

mylogger.warning("warning")

mylogger.error("error")

mylogger.critical("critical")

# opmysql.py

#!/usr/bin/env python3

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

'''

定义对mysql数据库基本操作的封装

1.单条数据的操作:insert,update,delete

2.查询数据表的一条数据

3.查询数据表的所有数据

'''

import pymysql

from mylogging import mylogger

class OpMysql:

'''mysql操作类,基于pymysql的封装'''

def __init__(self,host="127.0.0.1",username="root",password="",databasename="dsn"):

'''

初始化opmysql对象

:param host:数据库服务器地址

:param username:数据库用户名

:param password:用户的密码

:param databasename:要操作的库名称

'''

try:

self.conn = pymysql.connect(

host = host,

user = username,

password = password,

database = databasename,

charset = 'utf8', # 如果sql语句中存在中文字符的时候,需要在这里指定charset的参数,否则中文显示乱码

cursorclass = pymysql.cursors.DictCursor # pymysql默认select获取的数据是元祖类型,如果想要字典类型的数据,可以在这里统一设置

)

self.cur = self.conn.cursor() #创建游标

except pymysql.Error as e:

mylogger.info("[connection_message]-host:%s;user:%s;password:%s;database:%s"%(host,username,password,databasename))

mylogger.exception(e)

def op_sql(self,query,params=None):

'''

单条数据的操作,insert,update,delete

:param query:包含%s的sql字符串,当params=None的时候,不包含%s

:param params:一个元祖,默认为None

:return:如果执行过程没有crash,返回True,反之返回False

'''

try:

self.cur.execute(query,params)

self.conn.commit()

return True

except BaseException as e:

self.conn.rollback() #如果这里是执行的执行存储过程的sql命令,那么可能会存在rollback的情况,所以这里应该考虑到

mylogger.info("[sql_str_message]-%s"%self.cur.mogrify(query,params))

mylogger.exception(e)

return False

def select_one(self,query,params=None):

'''

查询数据表的单条数据

:param query: 包含%s的sql字符串,当params=None的时候,不包含%s

:param params: 一个元祖,默认为None

:return: 如果执行未crash,并以包含dict的列表的方式返回select的结果,否则返回错误代码001

'''

try:

self.cur.execute(query,params)

self.cur.scroll(0,"absolute") #光标回到初始位置,感觉自己的这句有点多余

return self.cur.fetchone()

except BaseException as e:

mylogger.info("[sql_str_message]-%s" % self.cur.mogrify(query, params))

mylogger.exception(e)

return "001" #错误代码001

def select_all(self,query,params=None):

'''

查询数据表的单条数据

:param query:包含%s的sql字符串,当params=None的时候,不包含%s

:param params:一个元祖,默认为None

:return:如果执行未crash,并以包含dict的列表的方式返回select的结果,否则返回错误代码001

'''

try:

self.cur.execute(query,params)

self.cur.scroll(0,"absolute") #光标回到初始位置,感觉这里得这句有点多余

return self.cur.fetchall()

except BaseException as e:

mylogger.info("[sql_str_message]-%s" % self.cur.mogrify(query, params))

mylogger.exception(e)

return "001" #错误代码001

def insert_many(self,query,params):

'''

向数据表中插入多条数据

:param query:包含%s的sql字符串,当params=None的时候,不包含%s

:param params:一个内容为元祖的列表

:return:如果执行过程没有crash,返回True,反之返回False

'''

try:

self.cur.executemany(query,params)

self.conn.commit()

return True

except BaseException as e:

self.conn.rollback()

mylogger.info("[sql_str_message]-%s" % self.cur.mogrify(query, params))

mylogger.exception(e)

return False

def __del__(self):

'''

当该对象的引用计数为0的时候,python解释器会自动执行__dell__方法,自动释放游标和链接

'''

self.cur.close()

self.conn.close()

if __name__ == "__main__":

# test

opmysql = OpMysql()

print(opmysql.select_one("SELECT * FROM user WHERE id = %s;",(1,)))

opmysql.select_one("SELECT * FROM user WHERE idd = %s;",("12",))

填坑指南

怎么样,看完上面的代码,你找到前面问题的答案没有,如果没有,继续看下去,我会给你参考链接,拿走学习吧。

【问】课程中每次使用logging的时候都需要设置输出格式信息,怎么封装

【答案】代码中有答案,同时可以参考这里

【问】希望整个系统公用一个logging实例,怎么做

【答案】单例模式(Singleton Pattern),是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在,当你希望在整个系统中,某个类只能出现一个实例的时候,单例对象就能派上用处,比如我们实践代码中的mylogging类就可以采用单例模式的方式来处理,节约内存资源。python中实现单例模式的方式有很多种,这里使用模块的方式来获得一个单例对象,具体实现方式,代码中有,自己找,当然你也可以参考这里

【问】除了捕获到Exception的时候需要输入log,还有什么时候需要输出log,才能帮助我在出现bug的时候定位问题

【答案】在错误日志里面除了有exception的具体内容而外,还应该打印sql信息,函数入参等,在报错的时候,除了提供的出错模块,行数,类型等信息之外,如果能够知道是在传递入什么内容之后执行出错的,可以更好的定位问题并分析原因。

【问】凡是有sql的地方都有sql注入的问题,所以,在封装的过程中,我们该怎么处理sql注入的问题 **

【答案】pymysql模块的execute/callproc方法的参数化语句自动防注入,所以我们在进行sql拼接的时候尽量使用pymysql的execute和callproc方法的参数化语句,具体可以查看我之前的笔记做了解《python3使用pymysql操作mysql》

这些都是课程里面没有覆盖到的地方,也是我自己在实践中的疑问和解决结果

好啦,暂时分享到这里,自己文笔真的太有限了,看来在未来,要好好研究一下写作了,不过,只要你们看得懂就行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值