【发布时间】:2013-11-23 14:41:03
【问题描述】:
我正在处理的程序遇到另一个问题。基本上,我的程序所做的是最多需要 4 个输入文件,处理它们并将我从它们收集的信息存储在我计算机上的 SQLite3 数据库中。这使我可以随时查看数据,而无需再次运行输入文件。该程序使用一个主脚本,它本质上只是一个 AUI Notebook,它导入一个输入脚本和输出脚本以用作面板。
要将数据添加到数据库中,我可以使用线程,因为我不会将结果直接返回到我的输出屏幕。但是,当我需要查看主表中的全部内容时,我最终会加载 25,000 条记录。当这些正在加载时,我的 GUI 被锁定并且几乎总是显示:“程序没有响应”。
我想使用线程/多处理从数据库中获取 25k 条记录并将它们加载到我的 ObjectListView 小部件中,以便我的 GUI 在此过程中仍然可用。当我尝试使用用于将数据添加到数据库的类似线程类时,我没有得到任何返回。当我说我一无所获时,我并没有夸大其词。
所以这是我的一个大问题,有没有办法在不使用全局变量的情况下线程化查询并返回结果?我无法通过我可以理解的示例找到解决方案,但我可能使用了错误的搜索字词。
以下是与当前问题相关的代码 sn-ps:
这是我用来确保数据已准备好用于我的 ObjectListView 小部件的方法。
class OlvMainDisplay(object):
def __init__(self, id, name, col01, col02, col03, col04, col05,
col06, col07, col08, col09, col10, col11,
col12, col13, col14, col15):
self.id = id
self.name = name
self.col01 = col01
self.col02 = col02
self.col03 = col03
self.col04 = col04
self.col05 = col05
self.col06 = col06
self.col07 = col07
self.col08 = col08
self.col09 = col09
self.col10 = col10
self.col11 = col11
self.col12 = col12
self.col13 = col13
self.col14 = col14
self.col15 = col15
我从中提取数据的 2 个表:
class TableMeta(base):
__tablename__ = 'meta_extra'
id = Column(String(20), ForeignKey('main_data.id'), primary_key=True)
col06 = Column(String)
col08 = Column(String)
col02 = Column(String)
col03 = Column(String)
col04 = Column(String)
col09 = Column(String)
col10 = Column(String)
col11 = Column(String)
col12 = Column(String)
col13 = Column(String)
col14 = Column(String)
col15 = Column(String)
class TableMain(base):
__tablename__ = 'main_data'
id = Column(String(20), primary_key=True)
name = Column(String)
col01 = Column(String)
col05 = Column(String)
col07 = Column(String)
extra_data = relation(
TableMeta, uselist=False, backref=backref('main_data', order_by=id))
我使用 2 个查询从这 2 个表中收集数据,一个获取所有记录,而另一个是函数定义的一部分,该函数定义采用多个字典并根据字典内容应用过滤器。这两个查询都是我的每个笔记本面板导入的主要“工人”脚本的一部分。
这是应用过滤器的函数:
def multiFilter(theFilters, table, anOutput, qType):
session = Session()
anOutput = session.query(table)
try:
for x in theFilters:
for attr, value in x.items():
anOutput = anOutput.filter(getattr(table, attr).in_(value))
except AttributeError:
for attr, value in theFilters.items():
anOutput = anOutput.filter(getattr(table, attr).in_(value))
anOutput = convertResults(anOutput.all())
return anOutput
session.close()
theFilters 可以是单个字典或字典列表,因此是“Try:”语句。一旦函数应用了过滤器,它就会通过另一个函数运行返回的结果,该函数将通过 OlvMainDisplay 类返回的每个结果放入一个列表中,然后传递给 OLV Widget。
还有一个大问题,有没有办法在不使用全局变量的情况下对查询(或多个查询)进行线程化并返回结果?或者可能一次抓取大约 200 条记录并将数据“分块”添加到 OLV 小部件?
提前谢谢你。
-迈克
--更新--
我已经查看了 "how to get the return value from a thread in python" 并且接受的答案没有返回任何内容或仍然锁定 GUI(不确定是什么导致了差异)。我想将创建的线程数限制在最多 5 个左右。
--新的更新-- 我对过滤器功能做了一些更正。
【问题讨论】:
-
快速更新:我仍在处理 SQLAlchemy 的查询并将结果返回到 ObjectListView,以便 GUI 不会被锁定和等待。但是,我能够测试 Mike Driscoll 的答案,并且实际上能够使用 VirtualObjectList 视图来提供一些帮助,但是使用它也删除了一些我不确定如何自己重新实现的东西。因此,我查看了我的“默认”查询代码并对其进行了改进,以将完全填充 OLV 所需的时间缩短到平均 34 秒。在我的问题中使用过滤代码比这要快得多。
标签: multithreading sqlite sqlalchemy wxpython objectlistview