pymysql读取大数据时候,用生成器生成数据异常退出

史艳文
  • 21

前提:本人要处理一个mysql表,数据大概500-600万的样子,通过遍历表进行数据的加工和清洗
操作:使用python3导入pymysql包进行操作,遇到二个问题,第一数据量太大,如果用常规连接然后不管是fetchone,fetchmany,fetchall都将占用大量加载时间,第二全部加载到内存,内存占用太高,(fetchone和fetchmany原理差不多,查了资料都说是先返回全部数据,然后遍历),不管fetchone和fetchmany说的对不对,占用大量时间,消耗大量内存是事实情况
解决:通过查看pymysql官方文档,官方文档写的是用无缓冲游标pymysql.cursors.SSCursor,这样速度确实加快了,我测试了代码确实加载速度很快
遇到的问题:当我用生成器生成读取的数据然后进行进一步使用时候,数据没有读完就报错误退出,而且我只是用300条测试数据就出错,报错信息提示是游标读取数据为None,然后异常退出,关键是每次读取数据量不等,然后报错,当我取消无缓冲游标方法,数据正确读完无异常

import pymysql
import time

class Check():
    def __init__(self, host, user, password,db,port=3306,charset="utf8"):
        self.host = host
        self.user = user
        self.password = password
        self.database = db
        self.port = port
        self.charset = charset
        try:
            self.conn = pymysql.connect(
                host=self.host,
                db=self.database,
                user=self.user,
                passwd=self.password,
                port=self.port,
                charset=self.charset,
                cursorclass=pymysql.cursors.SSCursor)  #无缓冲游标,当取消时候无异常
            self.cursor = self.conn.cursor()
        except:
            print('Mysql connect error!')

    def setDB(self,dbname):

        try:
            self.conn.select_db(dbname)
        except:
            print('select DB error')

    def queryAll(self, sql):

        try:
            self.cursor.execute(sql)
            while True:
                rows = self.cursor.fetchone()
                if rows:
                    yield rows
                    time.sleep(5)   #模拟其他操作
                else:
                    break
        except:
            print ('Get Data Error!')

    def commit(self):
        self.conn.commit()

    def close(self):
        self.cursor.close()
        self.conn.close()


if __name__ == '__main__':
    test = Check('127.0.0.1','root','123456','test')
    posts = test.queryAll('select * from posts ')
    a = 0
    for post in posts:
        print (post)
        a +=1
        print (a)
    print ("all down,%s",a)





回复
阅读 3.2k
1 个回答

你给的源码,测试300条数据毫无问题,每次执行均顺序执行并得出结果,python3.6.1 pymysql 0.8.0 mysql 5.7.21
怀疑可能是你的time.sleep(5) #模拟其他操作,使得mysql连接超时断开

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
你知道吗?

宣传栏