python dbutils库数据库连接池管理
1、 安装
支持 Python 3.7 到 3.12 版本
安装命令:pip install DBUtils
2、 使用
from dbutils.pooled_db import PooledDB
import pymysql
config = {
'host': host,
'user': user,
'password': password,
'port' : port ,
'database': db,
'charset': 'utf8mb4',
'cursorclass': pymysql.cursors.DictCursor,
'mincached': 1,
'maxcached': 2,
'maxshared': 0,
'maxconnections': 50,
'blocking': True,
'maxusage': None,
'setsession': [],
}
db_pool = PooledDB(pymysql, **config)
dsn = cx_Oracle.makedsn(host, port, service_name=service_name)
db_pool = PooledDB(
creator=cx_Oracle,
dsn=dsn,
user=user,
password=password,
maxconnections=10,
mincached=2,
maxcached=9,
maxshared=10,
blocking=True
)
db_pool = PooledDB(
creator=psycopg2,
maxconnections=6,
mincached=2,
blocking=True,
ping=0,
host = host,
port = port,
user = user,
password = password,
database = db)
conn = db_pool.connection()
cursor = conn.cursor()
try:
cursor.execute(sql)
result = cursor.fetchall()
if result:
for row in result:
for key, value in row.items():
if isinstance(value, Decimal):
row[key] = int(value)
cursor.close()
conn.close()
if result is not None:
return result
else:
return None
except Exception as e:
print(sql)
print(f"An error occurred: {e}")
cursor.close()
conn.close()
return False
3、封装成类使用
3.1 oracle示例
from dbutils.pooled_db import PooledDB
import cx_Oracle
from prettytable import from_db_cursor
class OracleDB:
def __init__(self,user,host, password, port,service_name):
"""
初始化数据库连接
:param host: 数据库主机地址
:param user: 数据库用户名
:param password: 数据库密码
:param db: 数据库名
建立数据库连接
"""
dsn = cx_Oracle.makedsn(host, port, service_name=service_name)
'''# 创建一个连接池
self.db_pool = cx_Oracle.SessionPool(user, password, dsn, min=1, max=20, increment=1,
homogeneous=True,
encoding="UTF-8",threaded=True, getmode=cx_Oracle.SPOOL_ATTRVAL_WAIT)'''
self.db_pool = PooledDB(
creator=cx_Oracle,
dsn=dsn,
user=user,
password=password,
maxconnections=10,
mincached=2,
maxcached=9,
maxshared=10,
blocking=True
)
def query(self, sql):
conn = self.db_pool.connection()
cursor = conn.cursor()
try:
cursor.execute(sql)
result = cursor.fetchall()
list_result = []
if result:
for i in result:
list_list = list(i)
des = cursor.description
t = ",".join([item[0] for item in des])
table_head = t.split(',')
dict_result = dict(zip(table_head, list_list))
list_result.append(dict_result)
cursor.close()
conn.close()
return list_result
except Exception as e:
print(f"exec {sql} An error occurred: {e}")
cursor.close()
conn.close()
return False
def query_table(self,sql):
"""
按prettytable格式返回查询结果,适用仅查询,展示格式比较友好
"""
try:
conn = self.db_pool.connection()
cursor = conn.cursor()
cursor.execute(sql)
table = from_db_cursor(cursor)
table.title = sql
return table
except Exception as e:
print(sql)
print(f"An error occurred: {e}")
return False
def execute(self, sql):
"""
单次执行非查询操作(如INSERT, UPDATE, DELETE)
"""
conn = self.db_pool.connection()
cursor = conn.cursor()
try:
cursor.execute(sql)
conn.commit()
cursor.close()
conn.close()
except Exception as e:
print(f"exec {sql} An error occurred: {e}")
cursor.close()
conn.close()
return False
def bat_execute(self, sql_list):
"""
批量执行sql,update\delete\insert操作,按2000条 commit一次
"""
conn = self.db_pool.connection()
cursor = conn.cursor()
count = 0
for sql in sql_list:
try:
cursor.execute(sql)
count += 1
if count % 2000 == 0:
conn.commit()
count = 0
except Exception as e:
print(f"exec {sql} An error occurred: {e}")
conn.rollback()
conn.close()
continue
if count > 0:
conn.commit()
cursor.close()
conn.close()
def close(self):
"""
关闭数据库连接
"""
self.db_pool.close()
3.2 mysql示例
from decimal import Decimal
import pymysql
from pymysql import converters,FIELD_TYPE
from dbutils.pooled_db import PooledDB
from prettytable import from_db_cursor
class MysqlPool:
def __init__(self, user,host, password,port, db):
"""
初始化数据库连接
:param host: 数据库主机地址
:param user: 数据库用户名
:param password: 数据库密码
:param db: 数据库名
"""
'''conv = converters.conversions
conv[FIELD_TYPE.NEWDECIMAL] = int # convert decimals to float
conv[FIELD_TYPE.DATE] = str # convert dates to strings
conv[FIELD_TYPE.TIMESTAMP] = str # convert dates to strings
conv[FIELD_TYPE.DATETIME] = str # convert dates to strings
conv[FIELD_TYPE.TIME] = str # convert dates to strings'''
config = {
'host': host,
'user': user,
'password': password,
'port' : port ,
'database': db,
'charset': 'utf8mb4',
'cursorclass': pymysql.cursors.DictCursor,
'mincached': 1,
'maxcached': 2,
'maxshared': 0,
'maxconnections': 50,
'blocking': True,
'maxusage': None,
'setsession': [],
}
self.db_pool = PooledDB(pymysql, **config)
def query(self, sql):
"""
执行查询操作
:return: 查询结果列表
"""
conn = self.db_pool.connection()
cursor = conn.cursor()
try:
cursor.execute(sql)
result = cursor.fetchall()
if result:
for row in result:
for key, value in row.items():
if isinstance(value, Decimal):
row[key] = int(value)
cursor.close()
conn.close()
if result is not None:
return result
else:
return None
except Exception as e:
print(sql)
print(f"An error occurred: {e}")
cursor.close()
conn.close()
return False
def query_table(self,sql):
conn = self.db_pool.connection()
cursor = conn.cursor()
try:
cursor.execute(sql)
mytable = from_db_cursor(cursor)
return mytable
except Exception as e:
print(sql)
print(f"An error occurred: {e}")
cursor.close()
conn.close()
return False
def execute(self, sql, params=None):
"""
执行非查询操作(如INSERT, UPDATE, DELETE)
# execute("insert into user(id, name, password) values (?, ?, ?)", [2, "李四", "123456"])
"""
conn = self.db_pool.connection()
cursor = conn.cursor()
try:
cursor.execute(sql, params)
except Exception as e:
print(f"An error occurred: {e}")
cursor.close()
conn.close()
return False
conn.commit()
cursor.close()
conn.close()
def bat_execute(self, sql_list):
"""
执行非查询操作(如INSERT, UPDATE, DELETE)
"""
conn = self.db_pool.connection()
cursor = conn.cursor()
count = 0
for sql in sql_list:
try:
cursor.execute(sql)
except Exception as e:
print(sql)
print(f"An error occurred: {e}")
conn.rollback()
cursor.close()
conn.close()
return False
count += 1
if count % 2000 == 0:
conn.commit()
count = 0
if count > 0:
conn.commit()
cursor.close()
conn.close()
3.3 PG库示例
import psycopg2
from dbutils.pooled_db import PooledDB
from prettytable import from_db_cursor
import pandas as pd
class Postgres:
def __init__(self, user,host, password,port, db):
"""
初始化数据库连接
:param host: 数据库主机地址
:param user: 数据库用户名
:param password: 数据库密码
:param db: 数据库名
"""
'''conv = converters.conversions
conv[FIELD_TYPE.NEWDECIMAL] = int # convert decimals to float
conv[FIELD_TYPE.DATE] = str # convert dates to strings
conv[FIELD_TYPE.TIMESTAMP] = str # convert dates to strings
conv[FIELD_TYPE.DATETIME] = str # convert dates to strings
conv[FIELD_TYPE.TIME] = str # convert dates to strings'''
self.db_pool = PooledDB(
creator=psycopg2,
maxconnections=6,
mincached=2,
blocking=True,
ping=0,
host = host,
port = port,
user = user,
password = password,
database = db)
def query(self, sql):
try:
conn = self.db_pool.connection()
cursor = conn.cursor()
cursor.execute(sql)
result = cursor.fetchall()
list_result = []
if result:
for i in result:
list_list = list(i)
des = cursor.description
t = ",".join([item[0] for item in des])
table_head = t.split(',')
dict_result = dict(zip(table_head, list_list))
list_result.append(dict_result)
cursor.close()
conn.close()
return list_result
except Exception as e:
print(f"An error occurred: {e}")
return False
def query_table(self,sql):
try:
conn = self.db_pool.connection()
cursor = conn.cursor()
cursor.execute(sql)
table = from_db_cursor(cursor)
table.title = sql
return table
except Exception as e:
print(sql)
print(f"An error occurred: {e}")
return False
def query_dataFrame(self,sql):
try:
conn = self.db_pool.connection()
cursor = conn.cursor()
cursor.execute(sql)
df = pd.DataFrame(cursor.fetchall(), columns=[desc[0] for desc in cursor.description])
return df
except Exception as e:
print(sql)
print(f"An error occurred: {e}")
return False
def execute(self, sql, params=None):
"""
执行非查询操作(如INSERT, UPDATE, DELETE)
"""
conn = self.db_pool.connection()
cursor = conn.cursor()
try:
cursor.execute(sql, params)
conn.commit()
cursor.close()
conn.close()
except Exception as e:
print(sql)
print(f"An error occurred: {e}")
cursor.close()
conn.close()
return False
def bat_execute(self, sql_list):
"""
执行非查询操作(如INSERT, UPDATE, DELETE)
"""
conn = self.db_pool.connection()
cursor = conn.cursor()
count = 0
for sql in sql_list:
try:
cursor.execute(sql)
except Exception as e:
print(sql)
print(f"An error occurred: {e}")
conn.rollback()
cursor.close()
conn.close()
return False
count += 1
if count % 2000 == 0:
conn.commit()
count = 0
if count > 0:
conn.commit()
cursor.close()
conn.close()
4 测试
if __name__ == "__main__":
oracle= OracleDB(oracle_info ['user'], oracle_info ['host'], oracle_info ['password'], int(oracle_info ['port']), oracle_info ['database'])
sql = 'select sysdate from dual'
print(oracle.query_table(sql))