使用来自MySQL查询的PyQt进行慢速PDF渲染

时间:2012-09-04 09:34:54

标签: python mysql sql pyqt

直到昨天,我还在为我的应用程序使用SQLite。今天我找到了一个足够强大的理由(多个应用程序实例),可以使用pymysql切换到MySQL。

有一次,我的应用程序在数据库中查询了300行:

cur.execute('select ime,brPredmeta,statusStr,sudskiBr ,sudija ,datumRasprave,statusPredmeta, zaduzen,datumZaduzenja from predmeti')
sviaktivni = cur.fetchall()
sviaktivni = list(sviaktivni) #make a list of tuples
sviaktivni.sort(key=operator.itemgetter(0)) #sort the list

之后,我提取变量,然后使用这些变量制作HTML文档,然后将其发送到打印机(PDF或普通打印机)。生成HTML的代码非常简单; “header”(为清晰起见,此处省略)的几行表,然后是“body”的另一个表,代码如下:

#extract the variables
for tuple in sviaktivni:
    ime,brPredmeta,statusStr,sudskiBr ,sudija ,datumRasprave,statusPredmeta, zaduzen,datumZaduzenja = tuple
#done extracting

  body = ('<html><head><title></title>'
    '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>'
    '<style></style>'
    '</head>'
    '<body>'
    '<table align ="center" border="0" width="100%" style="table-layout:fixed">'
    '<tr height="10%">'
    '<td align="left" width="20">'+str(brojac)+'.</td>'
    '<td align="left" width="180">'+ime+'</td>'
    '<td align="left" width="100">'+str(brPredmeta)+'</td>'
    '<td align="left" width="80">'+statusStr+'</td>'
    '<td align="left" width="80">'+str(sudskiBr)+'</td>'
    '<td align="left" width="140">'+sudija+'</td>'
    '<td align="left" width="150">'+zaduzen+'</td>'
    '<td align="left">'+datumZaduzenja+'</td>'
    '<td align="right"> '+statusPredmeta+' </td>'
    '</tr>'
    '</table>'
    '</body>'
    '</html>')

  self.ui.printHTML.append(body)

我的问题是查询是立即执行的,但是在CPU停留在100%之后,整个程序就冻结了。打印预览对话框有时会显示数据,有时它只是一个空窗口。无论哪种方式,整个应用程序都被冻结。

使用SQLite的相同代码没有问题。我该怎么办?回到sqlite并冒险数据库损坏?

2 个答案:

答案 0 :(得分:1)

不要只将整个SQL结果加载到内存中,并希望这适用于所有情况。此外,使用数据库为您进行排序,这就是它的优点。

只需循环遍历游标并逐个处理结果,这样就不必用中间结果填充内存:

cur.execute('''
    select 
        ime, brPredmeta, statusStr, sudskiBr, sudija,
        datumRasprave,statusPredmeta, zaduzen,datumZaduzenja
    from predmeti
    order by ime
    ''')
for row in cur:
    ime, brPredmeta, statusStr, sudskiBr, sudija, datumRasprave, statusPredmeta, zaduzen, datumZaduzenja = row
    # Process row data.

答案 1 :(得分:0)

取自SQLite Docs ...

  

可以是多个应用程序或多个相同的实例   应用程序同时访问单个数据库文件?

     

多个进程可以同时打开同一个数据库。   多个进程可以同时执行SELECT。但是只有   一个进程可以随时对数据库进行更改   然而,时间。

     

SQLite使用读取器/写入器锁来控制对数据库的访问。   (在Win95 / 98 / ME下,缺少对读写器锁的支持,a   改为使用概率模拟。)但要谨慎:这个   如果数据库文件是,锁定机制可能无法正常工作   保存在NFS文件系统上。这是因为fcntl()文件锁定是   在许多NFS实现上打破了。你应该避免使用SQLite   NFS上的数据库文件,如果多个进程可能尝试访问   同时提交文件。在Windows上,微软的文档说明了这一点   如果您没有运行,则锁定在FAT文件系统下可能无法正常工作   Share.exe守护程序。对Windows有很多经验的人   告诉我,网络文件的文件锁定是非常错误的,而不是   可信。如果他们说的是真的,那就共享一个SQLite数据库   两台或多台Windows机器之间可能会出现意外问题。

     

我们知道没有其他支持as的嵌入式SQL数据库引擎   和SQLite一样多并发。 SQLite允许多个进程拥有   数据库文件立即打开,并为多个进程读取   数据库一下子。当任何进程想要写入时,它必须锁定   整个数据库文件的更新期间。但通常情况下   只需几毫秒。其他进程只是等待作者   完成然后继续他们的业务。其他嵌入式SQL   数据库引擎通常只允许单个进程连接   数据库一下子。

     

但是,客户端/服务器数据库引擎(例如PostgreSQL,MySQL或   Oracle)通常支持更高级别的并发和允许   多个进程要同时写入同一个数据库   时间。这在客户端/服务器数据库中是可能的,因为存在   始终是一个可以协调的良好控制的服务器进程   访问。如果您的应用程序需要大量并发,那么   您应该考虑使用客户端/服务器数据库。但经验   表明大多数应用程序需要的并发性要比它们少得多   设计师想象。

     

当SQLite尝试访问被另一个进程锁定的文件时,   默认行为是返回SQLITE_BUSY。你可以调整它   使用sqlite3_busy_handler()或来自C代码的行为   sqlite3_busy_timeout()API函数。