(二十七)Flask之数据库连接池DBUtils库

目录:

  • 每篇前言:
  • DBUtils库
    • 模式一(底层使用threading.local实现):
    • 模式二:
  • Flask中使用
    • 方式一:直接将DBUtils初始化放到settings.py文件中
    • 方式二:从utils文件夹中导入
  • 脚本使用DBUtils代码demo:

每篇前言:

  • 🏆🏆作者介绍:【孤寒者】—CSDN全栈领域优质创作者、HDZ核心组成员、华为云享专家Python全栈领域博主、CSDN原力计划作者

  • 🔥🔥本文已收录于Flask框架从入门到实战专栏:《Flask框架从入门到实战》
  • 🔥🔥热门专栏推荐:《Python全栈系列教程》、《爬虫从入门到精通系列教程》、《爬虫进阶+实战系列教程》、《Scrapy框架从入门到实战》、《Flask框架从入门到实战》、《Django框架从入门到实战》、《Tornado框架从入门到实战》、《前端系列教程》。
  • 📝​📝本专栏面向广大程序猿,为的是大家都做到Python全栈技术从入门到精通,穿插有很多实战优化点。
  • 🎉🎉订阅专栏后可私聊进一千多人Python全栈交流群(手把手教学,问题解答); 进群可领取Python全栈教程视频 + 多得数不过来的计算机书籍:基础、Web、爬虫、数据分析、可视化、机器学习、深度学习、人工智能、算法、面试题等。
  • 🚀🚀加入我一起学习进步,一个人可以走的很快,一群人才能走的更远!

在这里插入图片描述

引子:

在上一个demo项目中,登录部分验证是直接写死的,本文模拟实际生产,查询MySQL数据库做验证。

一个很low的方法是:
项目根目录下创建utils/sql.py:

import pymysqlclass SQLHelper(object):@staticmethoddef open():conn = pymysql.connect(host='127.0.0.1', port=3306, password='123456', db='UserInfo')cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)return conn, cursor@staticmethoddef close(conn, cursor):conn.commit()cursor.close()conn.close()@classmethoddef fetch_one(cls, sql, args):conn, cursor = cls.open()cursor.execute(sql, args)obj = cursor.fetchone()cls.close(conn, cursor)return obj

在这里插入图片描述

上面这种用法很严重且明显的一个问题是: 每次登录一次都要和数据库创建一个连接!

解决方法就是使用DBUtils三方库:

DBUtils库

pip install DBUtils==1.3

DBUtils 是一套用于管理数据库连接池的Python包,为高频度高并发的数据库访问提供更好的性能,可以自动管理连接对象的创建和释放。并允许对非线程安全的数据库接口进行线程安全包装。

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

  1. PersistentDB:提供线程专用的数据库连接,并自动管理连接。

    为每个线程创建一个连接,线程即使调用了close方法,也不会关闭,只是把连接重新放到连接池,供自己线程再次使用。当线程终止时,连接自动关闭!

  2. PooledDB:提供线程间可共享的数据库连接,并自动管理连接。

    创建一批连接到连接池,供所有线程共享使用。

    PS:由于pymysql的threadsafety值为1,而DBUtils库用的内部又是用的pymysql,所以该模式连接池中的线程会被所有线程共享。

实测证明 PersistentDB 的速度是最高的(即第一种模式),但是在某些特殊情况下,数据库的连接过程可能异常缓慢,而此时的PooledDB(即模式二,所以推荐这个)则可以提供相对来说平均连接时间比较短的管理方式。

模式一(底层使用threading.local实现):

  • 了解即可~~~
from DBUtils.PersistentDB import PersistentDB
import pymysqlPOOL = PersistentDB(creator=pymysql,       # 连接数据库的模块maxusage=None,         # 一个数据库连接最多被重复使用的次数,None表示无限制setsession=[],         # 开始会话前执行的命令列表。如["set time zone ..."]ping=0,                # ping MySQL客户端,检查服务是否可用。  【一般用0,4,7】# 0 = None = never;  1 = default = whenever if is requested;  2 = when a cursor is created; 4 = when a query is executed;  7 = alwayscloseable=False,       # False:conn.close()实际上被忽略,供下次使用,在线程关闭时,才会自动关闭连接;True:conn.close()则关闭连接,再次调用就是一个新的连接了threadlocal=None,      # 本线程独享值的对象,用于保存链接对象,如果链接对象被重置,也清除host='127.0.0.1',port=6379,user='root',password='123456',database='UserInfo',charset='utf8'
)

使用:

def demo():conn = POOL.connection(shareable=False)cursor = conn.cursor()cursor.execute('select * from users')result = cursor.fetchall()cursor.close()  conn.close()

模式二:

  • 用这个~~~
from DBUtils.PooledDB import PooledDB
import pymysqlPOOL = PooledDB(creator=pymysql,       # 连接数据库的模块maxconnections=6,      # 连接池允许的最大连接数, 0和None表示不限制mincached=2,           # 初始化时,连接池中至少创建的空闲的连接,0表示不创建maxcached=5,           # 连接池中最多闲置的连接,0和None不限制maxshared=3,           # 连接池中最多共享的连接数量,0和None表示全部共享【默认为0,而且哪怕设置别的值也无用!!!下面会将为啥】blocking=True,         # 连接池中如果没有可用连接后,是否阻塞等待。True:等待;False:不等待直接报错maxusage=None,         # 一个连接最多被重复使用的次数,None表示无限制setsession=[],         # 开始会话前执行的命令列表。如["set time zone ..."]ping=0,                # ping MySQL客户端,检查服务是否可用。  【一般用0,4,7】# 0 = None = never;  1 = default = whenever if is requested;  2 = when a cursor is created; 4 = when a query is executed;  7 = alwayshost='127.0.0.1',port=6379,user='root',password='123456',database='UserInfo',charset='utf8'
)
  • 为什么设置maxshared参数的值是无用的!因为DBUtils使用的pymysql,而pymysql内部threadsafety值为1。看源码:

    import pymysql
    

    在这里插入图片描述

    DBUtils源码:

    from DBUtils.PooledDB import PooledDB
    

    在这里插入图片描述

使用:

def demo():"""检测当前正在运行连接数是否小于最大连接数;如果不小于则等待或报错:raise TooManyConnection异常否则则优先去初始化时创建的连接中获取连接:SteadyDBConnection然后将SteadyDBConnection对象封装到PooledDedicatedDBConnection中并返回。如果最开始创建的连接没有连接,则去创建一个SteadyDBConnection对象,再封装到PooledDedicatedDBConnection中并返回。一旦关闭连接后,连接就返回到连接池让后续线程继续使用~"""conn = POOL.connection()cursor = conn.cursor()cursor.execute('select * from users')result = cursor.fetchall()conn.close()

Flask中使用

方式一:直接将DBUtils初始化放到settings.py文件中

在这里插入图片描述
在这里插入图片描述

方式二:从utils文件夹中导入

在这里插入图片描述
在这里插入图片描述

脚本使用DBUtils代码demo:

# coding=utf-8
"""
使用DBUtils数据库连接池中的连接,操作数据库
"""
import datetime
import pymysql
from DBUtils.PooledDB import PooledDBclass MysqlClient(object):def __init__(self, **kwargs):self.pool = self.create_pool(**kwargs)self.connection = Noneself.cursor = Nonedef create_pool(self, **kwargs):return PooledDB(pymysql,mincached=kwargs.get('mincached', 10),maxcached=kwargs.get('maxcached', 20),maxshared=kwargs.get('maxshared', 10),maxconnections=kwargs.get('maxconnections', 200),blocking=kwargs.get('blocking', True),maxusage=kwargs.get('maxusage', 100),setsession=kwargs.get('setsession', None),reset=kwargs.get('reset', True),host=kwargs.get('host', '127.0.0.1'),port=kwargs.get('port', 3306),db=kwargs.get('db', 'mysqldemo'),user=kwargs.get('user', 'root'),passwd=kwargs.get('passwd', '123456'),charset=kwargs.get('charset', 'utf8mb4'),cursorclass=pymysql.cursors.DictCursor)def get_conn_cursor(self):self.connection = self.pool.connection()self.cursor = self.connection.cursor()def close(self):try:if self.cursor:self.cursor.close()if self.connection:self.connection.close()except Exception as e:print(e)def execute(self, sql, param=()):try:self.get_conn_cursor()count = self.cursor.execute(sql, param)print(count)return countfinally:self.close()def __dict_datetime_obj_to_str(self, result_dict):"""把字典里面的datetime对象转成字符串,使json转换不出错"""if result_dict:return {k: v.__str__() if isinstance(v, datetime.datetime) else v for k, v in result_dict.items()}return result_dictdef select_one(self, sql, param=()):"""查询单个结果"""try:self.get_conn_cursor()count = self.execute(sql, param)result = self.cursor.fetchone()result = self.__dict_datetime_obj_to_str(result)return count, resultfinally:self.close()def select_many(self, sql, param=()):"""查询多个结果"""try:self.get_conn_cursor()count = self.execute(sql, param)result = self.cursor.fetchall()result = [self.__dict_datetime_obj_to_str(row_dict) for row_dict in result]return count, resultfinally:self.close()def begin(self):"""开启事务"""try:self.get_conn_cursor()self.connection.autocommit(False)except Exception as e:print(e)def end(self, option='commit'):"""结束事务"""try:if option == 'commit':self.connection.commit()else:self.connection.rollback()except Exception as e:print(e)finally:self.connection.autocommit(True)if __name__ == "__main__":mc = MysqlClient()sql1 = 'SELECT * FROM customers  WHERE  customerNumber = 103'result1 = mc.select_one(sql1)print(result1[1])sql2 = 'SELECT * FROM customers  WHERE  customerNumber IN (%s,%s,%s)'param = (103, 144, 145)print(mc.select_many(sql2, param)[1])

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/807407.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt plugin 开发UI界面插件

目录 1.创建接口 2.创建插件 3.创建插件界面 4.插件实现 5.创建应用工程 6.应用插件 1.创建接口 打开QtCreater,点击左上角“文件”->新建文件或项目,在弹窗中选择C/CHeader File。 输入文件名,选好路径(可自行设置名称…

jsonpath在线解析器网址

jsonpath在线解析器网址:https://jsonpath.com/

手动实现简易版RPC(上)

手动实现简易版RPC(上) 前言 什么是RPC?它的原理是什么?它有什么特点?如果让你实现一个RPC框架,你会如何是实现?带着这些问题,开始今天的学习。 本文主要介绍RPC概述以及一些关于RPC的知识,为…

02-结构化程式与自定义函数

视频教程:b站视频【MATLAB教程_台大郭彦甫(14课)原视频补档】https://www.bilibili.com/video/BV1GJ41137UH/?share_sourcecopy_web&vd_sourc*ed6b9f96888e9c85118cb40c164875dfc 官网教程: MATLAB 快速入门 - MathWorks 中…

【动手学深度学习】15_汉诺塔问题

注: 本系列仅为个人学习笔记,学习内容为《算法小讲堂》(视频传送门),通俗易懂适合编程入门小白,需要具备python语言基础,本人小白,如内容有误感谢您的批评指正 汉诺塔(To…

基于springboot实现高校学科竞赛平台系统项目【项目源码+论文说明】

基于springboot实现高校学科竞赛平台系统演示 摘要 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了高校学科竞赛平台的开发全过程。通过分析高校学科竞赛平台管理的不足,创建了一个计算机管理高校学科竞…

day02 51单片机

51单片机学习 1闪烁LED 1.1 需求描述 这个案例,我们要让P00引脚对应的LED按照1秒闪烁1次。 1.2 硬件设计 1.1 软件设计 1)LED闪烁的代码 想让LED闪烁,就需要P00的值不断在0和1之间循环变化。实现这一功能的代码也很简单: #include <STC89C5xRC.H> //包含STC89…

超详细的 Python 文件操作知识!

python进行文件操作&#xff0c;在日常编程中是很常用的。为了方便大家&#xff0c;这里对各种文件操作的知识进行汇总。一文在手&#xff0c;无须它求&#xff01;来一起学习吧。 一、文件的打开和关闭 open()函数 f1 open(rd:\测试文件.txt, moder, encodingutf-8) conte…

《剑指 Offer》专项突破版 - 面试题 105 和 106 : 最大的岛屿和二分图(C++ 实现)

目录 面试题 105 : 最大的岛屿 面试题 106 : 二分图 面试题 105 : 最大的岛屿 题目&#xff1a; 海洋岛屿地图可以用由 0、1 组成的二维数组表示&#xff0c;水平或竖直方向相连的一组 1 表示一个岛屿&#xff0c;请计算最大的岛屿的面积&#xff08;即岛屿中 1 的数目&…

【MATLAB】基于Wi-Fi指纹匹配的室内定位-仿真获取WiFi RSSI数据(附代码)

基于Wi-Fi指纹匹配的室内定位-仿真获取WiFi RSSI数据 WiFi指纹匹配是室内定位最为基础和常见的研究&#xff0c;但是WiFi指纹的采集可以称得上是labor-intensive和time-consuming。现在&#xff0c;给大家分享一下我们课题组之前在做WiFi指纹定位时的基于射线跟踪技术仿真WiFi…

chrome 浏览器 有自带的自动字幕功能,支持英文,控制您的音乐、视频等媒体内容

chrome 浏览器 有自带的自动字幕功能&#xff0c;支持英文&#xff0c;控制您的音乐、视频等媒体内容

【机器学习算法】决策树和随机森林在计算机视觉中的应用

前言 决策树和随机森林在计算机视觉中有着广泛的应用。决策树作为一种简单而强大的分类模型&#xff0c;可以用于图像分类、目标检测、特征提取等任务。它能够根据图像的特征逐层进行判断和分类&#xff0c;从而实现对图像数据的智能分析和理解。随机森林作为一种集成学习方法&…

[dvwa] CSRF

CSRF 0x01 low 跨站&#xff0c;输入密码和确认密码直接写在url中&#xff0c;将连接分享给目标&#xff0c;点击后修改密码 社工方式让目标点击短链接 伪造404页&#xff0c;在图片中写路径为payload&#xff0c;目标载入网页自动请求构造链接&#xff0c;目标被攻击 http…

【STL】栈(stack)

笔者在做下面这道题的时候想到用栈&#xff0c;但写的很麻烦 代码&#xff1a; #include<bits/stdc.h> using namespace std; #define MAXC 255 typedef int SElemType; typedef struct StackNode {SElemType data;struct StackNode *next; }StackNode,*LinkStack; bool…

MathJax的基本使用

一、引言 MathJax引擎是一个开源的JavaScript库&#xff0c;它允许Web开发者在网页中嵌入高质量的数学公式。通过利用Web的最新技术&#xff0c;MathJax引擎可以解析LaTeX、MathML和AsciiMath等数学标记语言&#xff0c;并将其渲染为可视化的数学公式&#xff0c;这些公式可以…

NPU float(“inf“) mask_fill 出现NAN

使用NPU时&#xff0c;采用mask_fill函数&#xff0c;会出错&#xff1a; tensors.masked_fill(mask.unsqueeze(-1), float(inf)) 无法直接使用表达式,会报错 NAN&#xff1a; 取一个较大的值替换即可&#xff1b; tensors.masked_fill(mask.unsqueeze(-1), float(1e10))

LeetCode算法——双指针篇

宫侑的发球最终进化为三刀流&#xff0c;那么我的题解也未必要循规蹈矩! 1、验证回文串 题目描述&#xff1a; 解法&#xff1a; 这题官方给的关于双指针的题解都用到了多个库函数&#xff0c;如 tolower(大写字母转小写)、isalnum(判断一个字符是否是 字母 或者 十进制数字 )…

LeetCode——622设计循环队列

. - 力扣&#xff08;LeetCode&#xff09;. - 备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/design-circular-queue/ 1.题目 设计你的循环队列实现。 循环队列是一…

CSS-文字环绕浮动、行内块分页、三角强化妙用、伪元素选择器

文字环绕浮动 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>文字环绕浮动效果</title><s…

Vue+el-table 修改表格 单元格横线边框颜色及表格空数据时边框颜色

需求 目前 找到对应的css样式进行修改 修改后 css样式 >>>.el-table th.el-table__cell.is-leaf {border-bottom: 1px solid #444B5F !important;}>>>.el-table td.el-table__cell,.el-table th.el-table__cell.is-leaf {border-bottom: 1px solid #444B5F …