Python操作MySQL_pymysql args,2024年最新软件测试面试题高级

  • MySQLdb(目前仅支持python2.x)

2.ORM框架

  • SQLAchemy

2.1 PyMySQL模块

本文主要介绍PyMySQL模块,MySQLdb使用方式类似

2.1.1 安装PyMySQL
PyMySQL是一个Python编写的MySQL驱动程序,让我们可以用Python语言操作MySQL数据库。

pip install PyMySQL

2.2 基本使用

#! /usr/bin/env python

-*- coding: utf-8 -*-

author = “shuke”

Date: 2018/5/13

import pymysql

创建连接

conn = pymysql.connect(host=“127.0.0.1”, port=3306, user=‘zff’, passwd=‘zff123’, db=‘zff’, charset=‘utf8mb4’)

创建游标(查询数据返回为元组格式)

cursor = conn.cursor()

创建游标(查询数据返回为字典格式)

cursor = conn.cursor(pymysql.cursors.DictCursor)

1. 执行SQL,返回受影响的行数

effect_row1 = cursor.execute(“select * from USER”)

2. 执行SQL,返回受影响的行数,一次插入多行数据

effect_row2 = cursor.executemany(“insert into USER (NAME) values(%s)”, [(“jack”), (“boom”), (“lucy”)]) # 3

查询所有数据,返回数据为元组格式

result = cursor.fetchall()

增/删/改均需要进行commit提交,进行保存

conn.commit()

关闭游标

cursor.close()

关闭连接

conn.close()

print(result)
“”"
[{‘id’: 6, ‘name’: ‘boom’}, {‘id’: 5, ‘name’: ‘jack’}, {‘id’: 7, ‘name’: ‘lucy’}, {‘id’: 4, ‘name’: ‘tome’}, {‘id’: 3, ‘name’: ‘zff’}, {‘id’: 1, ‘name’: ‘zhaofengfeng’}, {‘id’: 2, ‘name’: ‘zhaofengfeng02’}]
“”"

2.3 获取最新创建的数据自增ID

#! /usr/bin/env python

-*- coding: utf-8 -*-

author = “shuke”

Date: 2018/5/13

import pymysql

创建连接

conn = pymysql.connect(host=“127.0.0.1”, port=3306, user=‘zff’, passwd=‘zff123’, db=‘zff’, charset=‘utf8mb4’)

创建游标(查询数据返回为元组格式)

cursor = conn.cursor()

获取新创建数据自增ID

effect_row = cursor.executemany(“insert into USER (NAME)values(%s)”, [(“eric”)])

增删改均需要进行commit提交

conn.commit()

关闭游标

cursor.close()

关闭连接

conn.close()

new_id = cursor.lastrowid
print(new_id)
“”"
8
“”"

2.4 查询操作

#! /usr/bin/env python

-*- coding: utf-8 -*-

author = “shuke”

Date: 2018/5/13

import pymysql

创建连接

conn = pymysql.connect(host=“127.0.0.1”, port=3306, user=‘zff’, passwd=‘zff123’, db=‘zff’, charset=‘utf8mb4’)

创建游标

cursor = conn.cursor()

cursor.execute(“select * from USER”)

获取第一行数据

row_1 = cursor.fetchone()

获取前n行数据

row_2 = cursor.fetchmany(3)

# 获取所有数据

row_3 = cursor.fetchall()

关闭游标

cursor.close()

关闭连接

conn.close()
print(row_1)
print(row_2)
print(row_3)

⚠️ 在fetch数据时按照顺序进行,可以使用cursor.scroll(num,mode)来移动游标位置,如:

  • cursor.scroll(1,mode=‘relative’) # 相对当前位置移动
  • cursor.scroll(2,mode=‘absolute’) # 相对绝对位置移动
    2.5 防止SQL注入

#! /usr/bin/env python

-*- coding: utf-8 -*-

author = “shuke”

Date: 2018/5/13

import pymysql

创建连接

conn = pymysql.connect(host=“127.0.0.1”, port=3306, user=‘zff’, passwd=‘zff123’, db=‘zff’, charset=‘utf8mb4’)

创建游标

cursor = conn.cursor()

存在sql注入情况(不要用格式化字符串的方式拼接SQL)

sql = “insert into USER (NAME) values(‘%s’)” % (‘zhangsan’,)
effect_row = cursor.execute(sql)

正确方式一

execute函数接受一个元组/列表作为SQL参数,元素个数只能有1个

sql = “insert into USER (NAME) values(%s)”
effect_row1 = cursor.execute(sql, [‘wang6’])
effect_row2 = cursor.execute(sql, (‘wang7’,))

正确方式二

sql = “insert into USER (NAME) values(%(name)s)”
effect_row1 = cursor.execute(sql, {‘name’: ‘wudalang’})

写入插入多行数据

effect_row2 = cursor.executemany(“insert into USER (NAME) values(%s)”, [(‘ermazi’), (‘dianxiaoer’)])

提交

conn.commit()

关闭游标

cursor.close()

关闭连接

conn.close()

这样,SQL操作就更安全了。如果需要更详细的文档参考PyMySQL文档吧。不过好像这些SQL数据库的实现还不太一样,PyMySQL的参数占位符使用%s这样的C格式化符,而Python自带的sqlite3模块的占位符好像是问号(?)。因此在使用其他数据库的时候还是仔细阅读文档吧。Welcome to PyMySQL’s documentation

三. 数据库连接池

上文中的方式存在一个问题,单线程情况下可以满足,程序需要频繁的创建释放连接来完成对数据库的操作,那么,我们的程序/脚本在多线程情况下会引发什么问题呢?此时,我们就需要使用数据库连接池来解决这个问题!

3.1 DBUtils模块

DBUtils是Python的一个用于实现数据库连接池的模块。

此连接池有两种连接模式:

  • 为每个线程创建一个连接,线程即使调用了close方法,也不会关闭,只是把连接重新放到连接池,供自己线程再次使用。当线程终止时,连接才会自动关闭
  • 创建一批连接到连接池,供所有线程共享使用(推荐使用)

3.2 模式一

#! /usr/bin/env python

-*- coding: utf-8 -*-

author = “shuke”

Date: 2018/5/13

from DBUtils.PersistentDB import PersistentDB
import pymysql

POOL = PersistentDB(
creator=pymysql, # 使用链接数据库的模块
maxusage=None, # 一个链接最多被重复使用的次数,None表示无限制
setsession=[], # 开始会话前执行的命令列表。如:[“set datestyle to …”, “set time zone …”]
ping=0,

ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always

closeable=False,

如果为False时, conn.close() 实际上被忽略,供下次使用,再线程关闭时,才会自动关闭链接。如果为True时, conn.close()则关闭链接,那么再次调用pool.connection时就会报错,因为已经真的关闭了连接(pool.steady_connection()可以获取一个新的链接)

threadlocal=None, # 本线程独享值得对象,用于保存链接对象,如果链接对象被重置
host=‘127.0.0.1’,
port=3306,
user=‘zff’,
password=‘zff123’,
database=‘zff’,
charset=‘utf8’,
)

def func():
conn = POOL.connection(shareable=False)
cursor = conn.cursor()
cursor.execute(‘select * from USER’)
result = cursor.fetchall()
cursor.close()
conn.close()
return result

result = func()
print(result)

3.2 模式二

#! /usr/bin/env python

-*- coding: utf-8 -*-

author = “shuke”

Date: 2018/5/13

import time
import pymysql
import threading
from DBUtils.PooledDB import PooledDB, SharedDBConnection

POOL = PooledDB(
creator=pymysql, # 使用链接数据库的模块
maxconnections=6, # 连接池允许的最大连接数,0和None表示不限制连接数
mincached=2, # 初始化时,链接池中至少创建的空闲的链接,0表示不创建
maxcached=5, # 链接池中最多闲置的链接,0和None不限制
maxshared=3,

链接池中最多共享的链接数量,0和None表示全部共享。PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。

blocking=True, # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错
maxusage=None, # 一个链接最多被重复使用的次数,None表示无限制
setsession=[], # 开始会话前执行的命令列表。如:[“set datestyle to …”, “set time zone …”]
ping=0,

ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always

host=‘127.0.0.1’,
port=3306,
user=‘zff’,
password=‘zff123’,
database=‘zff’,
charset=‘utf8’
)

def func():

检测当前正在运行连接数的是否小于最大链接数,如果不小于则:等待或报raise TooManyConnections异常

否则

则优先去初始化时创建的链接中获取链接 SteadyDBConnection。

然后将SteadyDBConnection对象封装到PooledDedicatedDBConnection中并返回。

如果最开始创建的链接没有链接,则去创建一个SteadyDBConnection对象,再封装到PooledDedicatedDBConnection中并返回。

一旦关闭链接后,连接就返回到连接池让后续线程继续使用。

conn = POOL.connection()

print(‘连接被拿走了’, conn._con)

print(‘池子里目前有’, POOL._idle_cache, ‘\r\n’)

cursor = conn.cursor()
cursor.execute(‘select * from USER’)
result = cursor.fetchall()
conn.close()
return result

result = func()
print(result)

⚠️ 由于pymysql、MySQLdb等threadsafety值为1,所以该模式连接池中的线程会被所有线程共享,因此是线程安全的。如果没有连接池,使用pymysql来连接数据库时,单线程应用完全没有问题,但如果涉及到多线程应用那么就需要加锁,一旦加锁那么连接势必就会排队等待,当请求比较多时,性能就会降低了。

3.3 加锁

#! /usr/bin/env python

-*- coding: utf-8 -*-

author = “shuke”

Date: 2018/5/13

import pymysql
import threading
from threading import RLock

LOCK = RLock()
CONN = pymysql.connect(host=‘127.0.0.1’,
port=3306,
user=‘zff’,
password=‘zff123’,

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数软件测试工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年软件测试全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上软件测试开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注软件测试)
img

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

4Z0P-1712984071642)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上软件测试开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注软件测试)
[外链图片转存中…(img-9T0bejfV-1712984071643)]

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值