Python pymysql 封装 整合数据库连接池

一、Python封装文件
mysql_server.py

#! /usr/bin/python
# -*- coding: UTF-8 -*-

import pymysql
from dbutils.pooled_db import PooledDB
from common.db.mysql_config import MysqlConfig

"""
    pymysql封装总结
    https://blog.csdn.net/zhj_1121/article/details/121070412
    
    python操作mysql之只看这篇就够了
    https://www.jianshu.com/p/4e72faebd27f
    
    关于PooledDB使用autocommit的方法
    https://blog.51cto.com/abyss/1736844
"""


class MysqlPool:
    """
    MySQL 数据库连接池类 配置变量
    """

    '''
        :param
        reset: how connections should be reset when returned to the pool
            (False or None to rollback transcations started with begin(),
            True to always issue a rollback for safety's sake)

        :param 
        setsession: optional list of SQL commands that may serve to prepare
            the session, e.g. ["set datestyle to ...", "set time zone ..."]
    '''

    '''
        https://blog.51cto.com/abyss/1736844
        其中的
        setsession=['SET AUTOCOMMIT = 1']
        就是用来设置线程池是否打开自动更新的配置,0为False,1为True
    '''

    # 初始化数据库连接池变量
    __pool = None

    # 创建连接池的最大数量
    __MAX_CONNECTIONS = 100
    # 连接池中空闲连接的初始数量
    __MIN_CACHED = 10
    # 连接池中空闲连接的最大数量
    __MAX_CACHED = 20
    # 共享连接的最大数量
    __MAX_SHARED = 10

    # 超过最大连接数量时候的表现,为True等待连接数量下降,为false直接报错处理
    __BLOCK = True
    # 单个连接的最大重复使用次数
    __MAX_USAGE = 100

    # 当返回到池时,连接应该如何重置
    # (False或None回滚以begin()开始的事务,为了安全起见,总是发出回滚)
    __RESET = True
    # 设置自动提交
    __SET_SESSION = ['SET AUTOCOMMIT = 1']

    # 不能是 UTF-8
    __CHARSET = 'UTF8'

    def __init__(self, host, port, user, password, database):
        """
        :param host: 数据库主机地址
        :param port: 端口号
        :param user: 用户名
        :param password: 密码
        :param database: 数据库名
        """
        if not self.__pool:
            # self代表当前类的实例,即为 MysqlPool() 带小括号,执行后的数据。
            # __class__,魔法函数,代表从当前类的实例中,获取当前类,即为 MysqlPool 不带小括号的类。
            # __pool,这个代表的事类的变量,即为在类下面创建的初始化连接池,__pool
            self.__class__.__pool = PooledDB(
                creator=pymysql,
                host=host,
                port=port,
                user=user,
                password=password,
                database=database,

                maxconnections=self.__MAX_CONNECTIONS,
                mincached=self.__MIN_CACHED,
                maxcached=self.__MAX_CACHED,
                maxshared=self.__MAX_SHARED,

                blocking=self.__BLOCK,
                maxusage=self.__MAX_USAGE,
                setsession=self.__SET_SESSION,
                reset=self.__RESET,

                charset=self.__CHARSET
            )

    def get_connect(self):
        return self.__pool.connection()


class MysqlCursor:
    """
    从数据库配置环境,取出数据库配置参数
    这里的参数,可以不从外部导入,直接手动写入也可以。
    """
    host = MysqlConfig().current_config()[0]
    port = MysqlConfig().current_config()[1]
    user = MysqlConfig().current_config()[2]
    password = MysqlConfig().current_config()[3]
    database = MysqlConfig().current_config()[4]

    def __init__(self, host=host, port=port, user=user, password=password, database=database) -> None:
        """
        :param host: 数据库主机地址
        :param port: 端口号
        :param user: 用户名
        :param password: 密码
        :param database: 数据库名
        """
        self.__host = host
        self.__port = port
        self.__user = user
        self.__password = password
        self.__database = database

        # 初始化数据库连接池
        self.connects_pool = MysqlPool(
            host=self.__host,
            port=self.__port,
            user=self.__user,
            password=self.__password,
            database=self.__database
        )

    def __enter__(self):
        """
        # with 上下文管理,魔法函数,进入with时调用
        :return: 当前类
        """
        # 从数据库链接池,获取一个数据库链接
        connect = self.connects_pool.get_connect()
        # 从获取的数据库链接,获取一个光标
        cursor = connect.cursor(pymysql.cursors.DictCursor)

        '''
        # https://blog.51cto.com/abyss/1736844
        # 如果使用连接池 则不能在取出后设置 而应该在创建线程池时设置
        # connect.autocommit = False 
        '''
        # 将数据库链接,赋值给当前类,方便__exit__函数调用
        self._connect = connect
        # 将数据库光标,赋值给当前类,方便__exit__函数调用
        self._cursor = cursor

        # __enter__函数,必须返回当前类
        return self

    def __exit__(self, *exc_info):
        """
        # with 上下文管理,魔法函数,退出with时调用
        :param exc_info: 异常信息,元祖
        :return: None
        """
        # 退出with上下文时,使用当前类链接,提交数据库语句
        self._connect.commit()
        # 关闭光标
        self._cursor.close()
        # 关闭链接
        self._connect.close()

    @property
    def cursor(self):
        """
        数据库连接池,取出链接,取出光标,转换为光标属性
        :return: 数据库连接池的光标
        """
        return self._cursor


if __name__ == "__main__":

    with MysqlCursor() as db:
        # 获取数据库的方法
        sql = 'select count(id) as total from people'
        db.cursor.execute("select count(id) as total from people")
        data = db.cursor.fetchone()
        print('--------统计数据条数', data)

你可能感兴趣的:(Python pymysql 封装 整合数据库连接池)