Python基于多线程操作数据库相关问题分析
本文实例分析了Python多线程操作数据库相关问题。分享给大家供大家参考,具体如下:
python多线程并发操作数据库,会存在链接数据库超时、数据库连接丢失、数据库操作超时等问题。
解决方法:使用数据库连接池,并且每次操作都从数据库连接池获取数据库操作句柄,操作完关闭连接返回数据库连接池。
*连接数据库需要设置charset = 'utf8', use_unicode = True,不然会报中文乱码问题
*网上说解决python多线程并发操作数据库问题,连接时使用self.conn.ping(True)(检查并保持长连接),但是我这边亲测无法解决,建议还是使用数据库连接池
python多线程代码:
import threading
class MyThread(threading.Thread):
def __init__(self, name, count, exec_object):
threading.Thread.__init__(self)
self.name = name
self.count = count
self.exec_object = exec_object
def run(self):
while self.count >= 0:
count = count - 1
self.exec_object.execFunc(count)
thread1 = MyThread('MyThread1', 3, ExecObject())
thread2 = MyThread('MyThread2', 5, ExecObject())
thread1.start()
thread2.start()
thread1.join() # join方法 执行完thread1的方法才继续主线程
thread2.join() # join方法 执行完thread2的方法才继续主线程
# 执行顺序 并发执行thread1 thread2,thread1和thread2执行完成才继续执行主线程
# ExecObject类是自定义数据库操作的业务逻辑类
#
########join方法详解########
thread1 = MyThread('MyThread1', 3, ExecObject())
thread2 = MyThread('MyThread2', 5, ExecObject())
thread1.start()
thread1.join() # join方法 执行完thread1的方法才继续主线程
thread2.start()
thread2.join() # join方法 执行完thread2的方法才继续主线程
# 执行顺序 先执行thread1,执行完thread1再执行thread2,执行完thread2才继续执行主线程
mysql数据库连接池代码:
import MySQLdb
from DBUtils.PooledDB import PooledDB
class MySQL:
host = 'localhost'
user = 'root'
port = 3306
pasword = ''
db = 'testDB'
charset = 'utf8'
pool = None
limit_count = 3 # 最低预启动数据库连接数量
def __init__(self):
self.pool = PooledDB(MySQLdb, self.limit_count, host = self.host, user = self.user, passwd = self.pasword, db = self.db,
port = self.port, charset = self.charset, use_unicode = True)
def select(self, sql):
conn = self.pool.connection()
cursor = conn.cursor()
cursor.execute(sql)
result = cursor.fetchall()
cursor.close()
conn.close()
return result
def insert(self, table, sql):
conn = self.pool.connection()
cursor = conn.cursor()
try:
cursor.execute(sql)
conn.commit()
return {'result':True, 'id':int(cursor.lastrowid)}
except Exception as err:
conn.rollback()
return {'result':False, 'err':err}
finally:
cursor.close()
conn.close()
更多关于Python相关内容感兴趣的读者可查看本站专题:《Python进程与线程操作技巧总结》、《Python数据结构与算法教程》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python入门与进阶经典教程》、《Python+MySQL数据库程序设计入门教程》及《Python常见数据库操作技巧汇总》
希望本文所述对大家Python程序设计有所帮助。
Python多线程原理与用法实例剖析
本文实例讲述了Python多线程原理与用法。分享给大家供大家参考,具体如下:
先来看个栗子:
下面来看一下I/O秘籍型的线程,举个栗子——爬虫,下面是爬下来的图片用4个线程去写文件
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import re
import urllib
import threading
import Queue
import timeit
def getHtml(url):
html_page = urllib.urlopen(url).read()
return html_page
# 提取网页中图片的URL
def getUrl(html):
pattern = r'src="(http://img.*?)"' # 正则表达式
imgre = re.compile(pattern)
imglist = re.findall(imgre, html) # re.findall(pattern,string) 在string中寻找所有匹配成功的字符串,以列表形式返回值
return imglist
class getImg(threading.Thread):
def __init__(self, queue, thread_name=0): # 线程公用一个队列
threading.Thread.__init__(self)
self.queue = queue
self.thread_name = thread_name
self.start() # 启动线程
# 使用队列实现进程间通信
def run(self):
global count
while (True):
imgurl = self.queue.get() # 调用队列对象的get()方法从队头删除并返回一个项目
urllib.urlretrieve(imgurl, 'E:\mnt\girls\%s.jpg' % count)
count += 1
if self.queue.empty():
break
self.queue.task_done() # 当使用者线程调用 task_done() 以表示检索了该项目、并完成了所有的工作时,那么未完成的任务的总数就会减少。
imglist = []
def main():
global imglist
url = "http://huaban.com/favorite/beauty/" # 要爬的网页地址
html = getHtml(url)
imglist = getUrl(html)
def main_1():
global count
threads = []
count = 0
queue = Queue.Queue()
# 将所有任务加入队列
for img in imglist:
queue.put(img)
# 多线程爬去图片
for i in range(4):
thread = getImg(queue, i)
threads.append(thread)
# 阻塞线程,直到线程执行完成
for thread in threads:
thread.join()
if __name__ == '__main__':
main()
t = timeit.Timer(main_1)
print t.timeit(1)
4个线程的执行耗时为:0.421320716723秒
修改一下main_1换成单线程的:
def main_1():
global count
threads = []
count = 0
queue = Queue.Queue()
# 将所有任务加入队列
for img in imglist:
queue.put(img)
# 多线程爬去图片
for i in range(1):
thread = getImg(queue, i)
threads.append(thread)
# 阻塞线程,直到线程执行完成
for thread in threads:
thread.join()
单线程的执行耗时为:1.35626623274秒
再来看一个:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import threading
import timeit
def countdown(n):
while n > 0:
n -= 1
def task1():
COUNT = 100000000
thread1 = threading.Thread(target=countdown, args=(COUNT,))
thread1.start()
thread1.join()
def task2():
COUNT = 100000000
thread1 = threading.Thread(target=countdown, args=(COUNT // 2,))
thread2 = threading.Thread(target=countdown, args=(COUNT // 2,))
thread1.start()
thread2.start()
thread1.join()
thread2.join()
if __name__ == '__main__':
t1 = timeit.Timer(task1)
print "countdown in one thread ", t1.timeit(1)
t2 = timeit.Timer(task2)
print "countdown in two thread ", t2.timeit(1)
task1是单线程,task2是双线程,在我的4核的机器上的执行结果:
countdown in one thread 3.59939150155
countdown in two thread 9.87704289712
天呐,双线程比单线程计算慢了2倍多,这是为什么呢,因为countdown是CPU密集型任务(计算嘛)
I/O密集型任务:线程做I/O处理的时候会释放GIL,其他线程获得GIL,当该线程再做I/O操作时,又会释放GIL,如此往复;
CPU密集型任务:在多核多线程比单核多线程更差,原因是单核多线程,每次释放GIL,唤醒的哪个线程都能获取到GIL锁,所以能够无缝执行(单核多线程的本质就是顺序执行),但多核,CPU0释放GIL后,其他CPU上的线程都会进行竞争,但GIL可能会马上又被CPU0(CPU0上可能不止一个线程)拿到,导致其他几个CPU上被唤醒后的线程会醒着等待到切换时间后又进入待调度状态,这样会造成线程颠簸(thrashing),导致效率更低。
更多关于Python相关内容感兴趣的读者可查看本站专题:《Python进程与线程操作技巧总结》、《Python数据结构与算法教程》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python入门与进阶经典教程》、《Python+MySQL数据库程序设计入门教程》及《Python常见数据库操作技巧汇总》
希望本文所述对大家Python程序设计有所帮助。
以上就是本次给大家分享的关于java的全部知识点内容总结,大家还可以在下方相关文章里找到相关文章进一步学习,感谢大家的阅读和支持。