一、DBUtils

DBUtils 是一套允许线程化 Python 程序可以安全和有效的访问数据库的模块,DBUtils提供两种外部接口: PersistentDB :提供线程专用的数据库连接,并自动管理连接。 PooledDB :提供线程间可共享的数据库连接,并自动管理连接。

操作数据库模板:

 import datetime
import sys
import os
import configparser
import logging
import psycopg2 from DBUtils.PooledDB import PooledDB class DatabaseOperator(object):
'''
class for database operator
''' def __init__(self,
database_config_path, database_config=None):
'''
Constructor
'''
self._database_config_path = database_config_path # load database configuration
if not database_config :
self._database_config = self.parse_postgresql_config(database_config_path)
else:
self._database_config = database_config
self._pool = None def database_config_empty(self):
if self._database_config:
return False
else:
return True def parse_postgresql_config(self, database_config_path=None):
'''解析pei数据库配置文件
参数
---------
arg1 : conf_file
数据库配置文件路径
返回值
--------
dict
解析配置属性dict--config 示例
--------

'''
if database_config_path == None and self._database_config_path != None:
database_config_path = self._database_config_path
if not os.path.isfile(database_config_path):
sys.exit("ERROR: Could not find configuration file: {0}".format(database_config_path))
parser = configparser.SafeConfigParser()
parser.read(database_config_path)
config = {}
config['database'] = parser.get('UniMonDB', 'Database')
config['db_user'] = parser.get('UniMonDB', 'UserName')
config['db_passwd'] = parser.get('UniMonDB', 'Password')
config['db_port'] = parser.getint('UniMonDB', 'Port')
config['db_host'] = parser.get('UniMonDB', 'Servername')
self._database_config = config return config def get_pool_conn(self): if not self._pool:
self.init_pgsql_pool()
return self._pool.connection() def init_pgsql_pool(self):
'''利用数据库属性连接数据库
参数
---------
arg1 : config
数据库配置属性
返回值
-------- 示例
--------

'''
# 字典config是否为空
config = self.parse_postgresql_config()
POSTGREIP = config['db_host']
POSTGREPORT = config['db_port']
POSTGREDB = config['database']
POSTGREUSER = config['db_user']
POSTGREPASSWD = config['db_passwd']
try:
logging.info('Begin to create {0} postgresql pool on:{1}.\n'.format(POSTGREIP, datetime.datetime.now())) pool = PooledDB(
creator=psycopg2, # 使用链接数据库的模块mincached
maxconnections=6, # 连接池允许的最大连接数,0和None表示不限制连接数
mincached=1, # 初始化时,链接池中至少创建的空闲的链接,0表示不创建
maxcached=4, # 链接池中最多闲置的链接,0和None不限制
blocking=True, # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错
maxusage=None, # 一个链接最多被重复使用的次数,None表示无限制
setsession=[], # 开始会话前执行的命令列表。
host=POSTGREIP,
port=POSTGREPORT,
user=POSTGREUSER,
password=POSTGREPASSWD,
database=POSTGREDB)
self._pool = pool
logging.info('SUCCESS: create postgresql success.\n') except Exception as e:
logging.error('ERROR: create postgresql pool failed:{0}\n')
self.close_db_cursor()
sys.exit('ERROR: create postgresql pool error caused by {0}'.format(str(e))) def pg_select_operator(self, sql):
'''进行查询操作,函数返回前关闭cursor,conn
参数
---------
arg1 : sql查询语句
返回值
--------
list:result
类型为list的查询结果:result 示例
--------

'''
# 执行查询
try:
conn = self.get_pool_conn()
cursor = conn.cursor()
cursor.execute(sql)
result = cursor.fetchall()
except Exception as e:
logging.error('ERROR: execute {0} causes error'.format(sql))
sys.exit('ERROR: load data from database error caused {0}'.format(str(e)))
finally:
cursor.close()
conn.close()
return result def test_pool_con(self):
sql = 'select * from tbl_devprofile'
result = self.pg_select_operator(sql)
print(result) def pg_insert_operator(self, sql): result = False
try:
conn = self.get_pool_conn()
cursor = conn.cursor()
cursor.execute(sql)
result = True
except Exception as e:
logging.error('ERROR: execute {0} causes error'.format(sql))
sys.exit('ERROR: insert data from database error caused {0}'.format(str(e)))
finally:
cursor.close()
conn.commit()
conn.close()
return result def pg_update_operator(self, sql): result = False
try:
conn = self.get_pool_conn()
cursor = conn.cursor()
cursor.execute(sql)
result = True
except Exception as e:
logging.error('ERROR: execute {0} causes error'.format(sql))
sys.exit('ERROR: update data from database error caused {0}'.format(str(e)))
finally:
cursor.close()
conn.commit()
conn.close()
return result def pg_delete_operator(self, sql):
result = False
# 执行查询
try:
conn = self.get_pool_conn()
cursor = conn.cursor()
cursor.execute(sql)
result = True
except Exception as e:
logging.error('ERROR: execute {0} causes error'.format(sql))
sys.exit('ERROR: delete data from database error caused {0}'.format(str(e)))
finally:
cursor.close()
conn.commit()
conn.close()
return result def close_pool(self):
'''关闭pool
参数
---------
无 返回值
--------

示例
--------

'''
if self._pool != None:
self._pool.close() if __name__ == '__main__':
path = "E:\\Users\\Administrator\\eclipse-workspace\\com.leagsoft.basemodule\\base\\config\\sql_conf.conf"
db = DatabaseOperator(
database_config_path=path)
db.test_pool_con()

二、多线程

原理:创建多个线程类,多个线程类共享一个队里Queue,每一个线程类可以操作数据库

 from threading import Thread

 class Worker(Thread):
def __init__(self, queue):
Thread.__init__(self)
self.queue = queue def run(self):
while True:
# Get the work from the queue and expand the tuple
# 从队列中获取任务
database_operator, device, stand_alone_result = self.queue.get()
operateResult(database_operator, device, stand_alone_result)
# 任务执行完之后要通知队列
self.queue.task_done()

填充队列

     # 使用队列多线程
logging.info('begin to update all device risk score by multi_processing.\n')
from queue import Queue
queue = Queue()
# 六个线程,每个线程共享一个队列
for _ in range(6):
worker = Worker(queue)
worker.setDaemon(True)
worker.start() for record in all_devid:
device = record[0]
devtype = record[1]
all_countlist = all_dict.get(device)
stand_alone_result = device_assess(all_countlist)
if (devtype in (server_devtype + computer_devtype)) and (stand_alone_result < 100):
stand_alone_result *= 0.8
# 将设备风险评分数据保存到数据库中
queue.put((database_operator, device, stand_alone_result)) #等待队列任务执行完
queue.join() def operateResult(database_operator, device, stand_alone_result):
'''
函数名称: device_assess
描述: 保存单台设备分数到数据库
调用: 无
被调用: main
被访问的表: tbl_devprofile
被修改的表: 无
输入参数: database_operator, device:设备uid, stand_alone_result:单台设备风险分数
输出参数:无
返回值: 单台设备风险分数值
其它: 无
'''
import time
find_profile_sql = "SELECT uiddevrecordid FROM tbl_devprofile WHERE uiddevrecordid='{0}';".format(device)
isExistRecord = database_operator.pg_select_operator(find_profile_sql)
#currentTime=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
currentTime=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
if len(isExistRecord) > 0:
updata_profile_sql = "UPDATE tbl_devprofile SET irisklevel={0}, dtrisktime='{1}' \
WHERE uiddevrecordid='{2}';".format(stand_alone_result, currentTime, device)
database_operator.pg_update_operator(updata_profile_sql)
else:
insert_profile_sql = "INSERT INTO tbl_devprofile VALUES('{0}',NULL,NULL,NULL,NULL,NULL,NULL,NULL,{1},'{2}');".format(
device, stand_alone_result, currentTime)
database_operator.pg_insert_operator(insert_profile_sql)

使用单线程时,执行完代码花费20s左右,使用多线程时花费5s左右。

Reference:

[1] https://blog.csdn.net/zhaihaifei/article/details/54016939

[2] https://www.cnblogs.com/hao-ming/p/7215050.html?utm_source=itdadao&utm_medium=referral

[3] https://www.cnblogs.com/wozijisun/p/6160065.html (多线程)

[4] http://www.lpfrx.com/archives/4431/

[5] https://www.cnblogs.com/95lyj/p/9047554.html

python DBUtils 线程池 连接 Postgresql(多线程公用线程池,DB-API : psycopg2)的更多相关文章

  1. Java中线程的使用 (2)-多线程、线程优先级、线程睡眠、让步、阻塞

    Java中线程的使用 (2)-多线程.线程优先级.线程睡眠.让步.阻塞 (一)多线程使用方法 说明:创建每个新的线程,一定要记得启动每个新的线程(调用.start()方法) class Xc3 ext ...

  2. 【死磕线程】线程同步机制_java多线程之线程锁

    1.线程各种状态间的切换,用图表示的话简单清晰: 图出处:https://www.cnblogs.com/bhlsheji/p/5099362.html(博主对每个状态解释的清晰明了) 2.为什么需要 ...

  3. python - DBUtils 连接池减少oracle数据库的连接数

    问题: 接到需求,告知项目的oracle连接次数过多,对系统造成太过大的负担,要求减少oracle数据库的连接次数 分析: 仔细分析代码以后,发现产生问题的原因,在于之前要求提升oracle监控的监控 ...

  4. Python 多线程和线程池

    一,前言 进程:是程序,资源集合,进程控制块组成,是最小的资源单位 特点:就对Python而言,可以实现真正的并行效果 缺点:进程切换很容易消耗cpu资源,进程之间的通信相对线程来说比较麻烦 线程:是 ...

  5. python使用dbutils的PooledDB连接池,操作数据库

    1.使用dbutils的PooledDB连接池,操作数据库. 这样就不需要每次执行sql后都关闭数据库连接,频繁的创建连接,消耗时间 2.如果是使用一个连接一直不关闭,多线程下,插入超长字符串到数据库 ...

  6. python(13)多线程:线程池,threading

    python 多进程:多进程 先上代码: pool = threadpool.ThreadPool(10) #建立线程池,控制线程数量为10 reqs = threadpool.makeRequest ...

  7. python爬虫14 | 就这么说吧,如果你不懂python多线程和线程池,那就去河边摸鱼!

    你知道吗? 在我的心里 你是多么的重要 就像 恩 请允许我来一段 freestyle 你们准备好了妹油 你看 这个碗 它又大又圆 就像 这条面 它又长又宽 你们 在这里 看文章 觉得 很开心 就像 我 ...

  8. python基础-12 多线程queue 线程交互event 线程锁 自定义线程池 进程 进程锁 进程池 进程交互数据资源共享

    Python中的进程与线程 学习知识,我们不但要知其然,还是知其所以然.你做到了你就比别人NB. 我们先了解一下什么是进程和线程. 进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CP ...

  9. Python多线程、线程池及实际运用

    我们在写python爬虫的过程中,对于大量数据的抓取总是希望能获得更高的速度和效率,但由于网络请求的延迟.IO的限制,单线程的运行总是不能让人满意.因此有了多线程.异步协程等技术. 下面介绍一下pyt ...

随机推荐

  1. 前端工程化系列[02]-Grunt构建工具的基本使用

    本文主要介绍前端开发中常用的构建工具Grunt,具体包括Grunt的基本情况.安装.使用和常见插件的安装.配置和使用等内容. 1.1 Grunt简单介绍 Grunt是一套前端自动化构建工具.对于需要反 ...

  2. SharePoint PowerShell 启动工作流

    前言 最近,有个需求,就是需要批量更新列表内容,平时这些操作,都用powershell去完成,但是,powershell需要在服务器上操作,而服务器权限需要通过客户的层层把关,所以,这次就考虑不用命令 ...

  3. springboot拦截器@Autowired为null解决

    问题原因 拦截器加载的时间点在springcontext之前,所以在拦截器中注入自然为null 文件解决 在spring配置文件中这样写 @Bean public HandlerInterceptor ...

  4. ceph:如何处理rados --striper上传失败的对象

    如何处理使用rados --striper上传失败的对象? `Remove striped objects from a ceph pool without using the striper lib ...

  5. 【转】Wireshark和Fiddler分析Android中的TLS协议包数据(附带案例样本)

    本文转自:http://www.wjdiankong.cn/wireshark%E5%92%8Cfiddler%E5%88%86%E6%9E%90android%E4%B8%AD%E7%9A%84tl ...

  6. HTTPS IP直连问题小结

    HTTPS IP直连问题小结: https://blog.csdn.net/leelit/article/details/77829196 可以使用OkHttpClient进行相同IP地址,不同DNS ...

  7. [Python设计模式] 第19章 分公司=部门?——组合模式

    github地址:https://github.com/cheesezh/python_design_patterns 组合模式 组合模式,将对象组合成树形结构以表示"部分-整体" ...

  8. ionic android升级检查

    https://www.cnblogs.com/zxj159/p/4421578.html 坑: 放到cordova.file.DataDirectory下载异常? 只好cordova.file.ex ...

  9. 在 System.Web.Mvc.DefaultModelBinder.ConvertProviderRe

    在 System.Web.Mvc.ValueProviderResult.ConvertSimpleType(CultureInfo culture, Object value, Type desti ...

  10. Sql Server 增加字段、修改字段、修改类型、修改默认值(转)

    转:http://www.cnblogs.com/pangpanghuan/p/6432331.html Sql Server 增加字段.修改字段.修改类型.修改默认值 1.修改字段名: alter ...