日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

python pymysql multiprocessing.dummy多线程 读写数据库报错

發(fā)布時間:2023/12/18 数据库 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python pymysql multiprocessing.dummy多线程 读写数据库报错 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

  • 一、例子
  • 二、報錯及原因
  • 三、解決方法
    • 1.在每個execute前加上互斥鎖
    • 2.在pool1.map(func, list)中參數(shù)的func函數(shù)中,實例化一個數(shù)據(jù)庫對象
    • 3.在KsMySql數(shù)據(jù)庫鏈接類中使用數(shù)據(jù)庫鏈接池獲取鏈接,將pool鏈接池為類對象


一、例子

  • 需求
    使用多線程下載視頻到本地,將視頻的名字保存在數(shù)據(jù)庫表中,數(shù)據(jù)庫表中不能保存重復視頻名字
  • demo.py
from multiprocessing.dummy import Pool import traceback import requests import pymysql import os # 習慣函數(shù)名開頭大寫,變量名開頭小寫,還沒適應(yīng)Python寫代碼規(guī)范,見諒# 數(shù)據(jù)庫鏈接類 class KsMySql:def __init__(self):self.conn = pymysql.Connect(host='127.0.0.1', port=3306, user='root', password='1234567', db='pythonspider', charset='utf8mb4') # 普通鏈接self.cursor = self.conn.cursor()# 是否保存過了通過視頻名稱查找, 返回true為不存在,false為存在def IsSaveVideoByName(self, filename):try:self.cursor.execute('select * from ksvideoinfo where filename = "%s"' %(filename))result = self.cursor.fetchone()return result is not Noneexcept:print('IsSaveVideoByName 查詢錯誤')traceback.print_exc()return True# 插入視頻信息def SaveVideoInfo(self, filename):try:self.cursor.execute('insert into ksvideoinfo(filename) values("%s")'%(filename))self.conn.commit()print('SaveVideoInfo 插入數(shù)據(jù)成功')except Exception as e:self.conn.rollback()print('SaveVideoInfo 插入數(shù)據(jù)錯誤')print(e)traceback.print_exc()def __del__(self):self.cursor.close()self.conn.close()# 全局變量 ksmysql = KsMySql()# 數(shù)據(jù)庫類實例 infolist = [] dirName = 'E:/AllWorkSpace1/Pytharm/pythonProjectPaWeb/Testdemo'# 保存目錄 if not os.path.exists(dirName):os.mkdir(dirName)def Select():name = '楊洋迪麗熱巴《煙火星辰》,用歌聲致敬中國航天'# 需求3:數(shù)據(jù)庫表中不能保存重復視頻名字(這里只是模擬)isSave = ksmysql.IsSaveVideoByName(name)# 為了方便,默認為不存在,直接添加url到list中mp4url = 'https://video.pearvideo.com/mp4/short/20220206/cont-1751191-15823342-hd.mp4'infolist.append({'name': name, 'videoUrl': mp4url})def SaveInfo(dic):name = dic['name']pathName = dirName + '/' + name + '.mp4'url = dic['videoUrl']try:# if not os.path.exists(pathName):mp4Data = requests.get(url=url).content # 從網(wǎng)絡(luò)下載視頻with open(pathName, 'wb') as f:# 需求1:視頻保存在本地f.write(mp4Data)print(name, "下載完成")# else:# print(name,'已存在,無需下載')# 需求2:視頻的名字保存在數(shù)據(jù)庫表中ksmysql.SaveVideoInfo(name)except Exception as e:print(name, '下載失敗失敗或者保存數(shù)據(jù)庫失敗')print(e)traceback.print_exc()def Main():pool1 = Pool(20) # 線程池for cur in range(0, 100):infolist.clear()Select()pool1.map(SaveInfo, infolist) # 使用多線程下載pool1.close()pool1.join()Main()

二、報錯及原因

  • 常見錯誤
    1). Packet sequence number wrong
    2). Exception _mysql_exceptions.OperationalError: (2013, ‘Lost connection to MySQL server during query’)
    3). pymysql AttributeError: ‘NoneType‘ object has no attribute ‘settimeout‘
  • 原因
    如上demo.py,是因為各個線程共享同一個數(shù)據(jù)庫鏈接而導致的錯誤

三、解決方法

1.在每個execute前加上互斥鎖

如:

...同上 import threading class KsMySql:def __init__(self):self.conn = pymysql.Connect(host='127.0.0.1', port=3306, user='root', password='tiger', db='pythonspider', charset='utf8mb4') # 普通鏈接self.cursor = self.conn.cursor()self.lock = threading.Lock()# 實例化# 是否保存過了通過視頻名稱查找, 返回true為不存在,false為存在def IsSaveVideoByName(self, filename):try:self.lock.acquire() # 上鎖self.cursor.execute('select * from ksvideoinfo where filename = "%s"' %(filename))result = self.cursor.fetchone()self.lock.release() # 解鎖return result is not Noneexcept:print('IsSaveVideoByName 查詢錯誤')traceback.print_exc()return True ...同上

但經(jīng)過我個人測試發(fā)現(xiàn),沒有用,還是會報新錯,這個方法理論上是沒問題的,但是在multiprocessing.dummy多線程情況下卻不行。僅代表我個人想法,也許自己能力不足,哪里寫錯了

2.在pool1.map(func, list)中參數(shù)的func函數(shù)中,實例化一個數(shù)據(jù)庫對象

... def SaveInfo(dic):ksmysql = KsMySql()# 數(shù)據(jù)庫類實例name = dic['name']pathName = dirName + '/' + name + '.mp4'url = dic['videoUrl']try:# if not os.path.exists(pathName):mp4Data = requests.get(url=url).content # 從網(wǎng)絡(luò)下載視頻with open(pathName, 'wb') as f:# 需求1:視頻保存在本地f.write(mp4Data)print(name, "下載完成")# else:# print(name,'已存在,無需下載')# 需求2:視頻的名字保存在數(shù)據(jù)庫表中ksmysql.SaveVideoInfo(name)except Exception as e:print(name, '下載失敗失敗或者保存數(shù)據(jù)庫失敗')print(e)traceback.print_exc() ...

可以完美解決,因為這樣每個線程都有自己的數(shù)據(jù)庫鏈接對象。
優(yōu)點:簡單、方便
缺點:每調(diào)用SaveInfo函數(shù)一次就建立一個數(shù)據(jù)庫鏈接,并函數(shù)結(jié)束時關(guān)閉鏈接,可能性能有損

3.在KsMySql數(shù)據(jù)庫鏈接類中使用數(shù)據(jù)庫鏈接池獲取鏈接,將pool鏈接池為類對象

... from dbutils.pooled_db import PooledDBclass KsMySql:pool = Nonedef __init__(self):# self.conn = pymysql.Connect(host='127.0.0.1', port=3306, user='root', password='tiger', db='pythonspider', charset='utf8mb4') # 普通鏈接,每實例化一個對象就會新建一個鏈接self.conn = KsMySql.Getmysqlconn()# 從鏈接池中獲取鏈接self.cursor = self.conn.cursor()# 靜態(tài)方法@staticmethoddef Getmysqlconn():if KsMySql.pool is None:mysqlInfo = {"host": '127.0.0.1',"user": 'root',"passwd": 'tiger',"db": 'pythonspider',"port": 3306,"charset": 'utf8mb4'}KsMySql.pool = PooledDB(creator=pymysql, mincached=1, maxcached=20, host=mysqlInfo['host'],user=mysqlInfo['user'], passwd=mysqlInfo['passwd'], db=mysqlInfo['db'],port=mysqlInfo['port'], charset=mysqlInfo['charset'], blocking=True)print(KsMySql.pool)# else:# print('新KsMySql實例,從數(shù)據(jù)庫鏈接池獲取鏈接')return KsMySql.pool.connection()...def __del__(self):# 鏈接不是真正的被關(guān)閉,而是放回鏈接池中self.cursor.close()self.conn.close()def SaveInfo(dic):ksmysql = KsMySql()# 同樣要寫上實例化數(shù)據(jù)庫類對象... ...

注意

KsMySql.pool = PooledDB(creator=pymysql, mincached=1, maxcached=20, host=mysqlInfo['host'],user=mysqlInfo['user'], passwd=mysqlInfo['passwd'], db=mysqlInfo['db'],port=mysqlInfo['port'], charset=mysqlInfo['charset'], blocking=True) ''' blocking參數(shù),代表當鏈接都被占用了,是否等待新的空閑鏈接 True :等待, 可能影響程序速度 False:不等待,(個人猜測。。好像是代表同用已占有的數(shù)據(jù)庫鏈接對象,會重復一開始的報錯),反正會報錯,最好寫成True '''

可以完美解決,因為這樣每個線程也都有自己的數(shù)據(jù)庫鏈接對象。
優(yōu)點:從鏈接池中獲取自己的鏈接,優(yōu)化點性能把
缺點:代碼稍微復雜,坑多。。。

總結(jié)

以上是生活随笔為你收集整理的python pymysql multiprocessing.dummy多线程 读写数据库报错的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。