Multithreading 多线程SQLAlchemy并将结果返回到ObjectListView
我在做一个程序时遇到了另一个问题。基本上,我的程序所做的是,它最多需要4个输入文件,对它们进行处理,并将我从中收集的信息存储在计算机上的SQLite3数据库中。这使我可以随时查看数据,而无需再次运行输入文件。该程序使用一个主脚本,它本质上只是一个AUI笔记本,用于导入输入脚本,并将输出脚本用作面板 要将数据添加到数据库,我可以使用线程,因为我不会将结果直接返回到输出屏幕。然而,当我需要查看主表中的全部内容时,我最终得到了25000条正在加载的记录。当这些正在加载时,我的GUI被锁定,并且几乎总是显示:“程序没有响应” 我希望使用线程/多处理从数据库中获取25k条记录,并将它们加载到ObjectListView小部件中,以便在此过程中我的GUI仍然可用。当我尝试使用类似的线程类将数据添加到数据库时,我没有得到任何返回。当我说我什么也得不到的时候,我并没有夸张 这是我的一个大问题,有没有一种方法可以在不使用全局变量的情况下执行查询并返回结果?我无法找到一个我能理解的例子的解决方案,但我可能使用了错误的搜索词 以下是与当前问题相关的代码片段: 这就是我用来确保ObjectListView小部件的数据准备就绪的方法Multithreading 多线程SQLAlchemy并将结果返回到ObjectListView,multithreading,sqlite,sqlalchemy,wxpython,objectlistview,Multithreading,Sqlite,Sqlalchemy,Wxpython,Objectlistview,我在做一个程序时遇到了另一个问题。基本上,我的程序所做的是,它最多需要4个输入文件,对它们进行处理,并将我从中收集的信息存储在计算机上的SQLite3数据库中。这使我可以随时查看数据,而无需再次运行输入文件。该程序使用一个主脚本,它本质上只是一个AUI笔记本,用于导入输入脚本,并将输出脚本用作面板 要将数据添加到数据库,我可以使用线程,因为我不会将结果直接返回到输出屏幕。然而,当我需要查看主表中的全部内容时,我最终得到了25000条正在加载的记录。当这些正在加载时,我的GUI被锁定,并且几乎总是
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
我从以下两个表中提取数据:
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))
我使用两个查询从这两个表中收集数据,一个获取所有记录,而另一个是函数定义的一部分,该函数定义使用多个字典并根据字典内容应用过滤器。这两个查询都是我的主“worker”脚本的一部分,该脚本由我的每个笔记本面板导入
以下是应用过滤器的函数:
过滤器可以是单个词典,也可以是词典列表,因此使用“Try:”语句。一旦该函数应用了过滤器,它就会通过另一个函数运行返回的结果,该函数将通过OlvMainDisplay类返回的每个结果放入一个列表中,并将其传递给OLV小部件
还有一个大问题,是否有一种方法可以在不使用全局变量的情况下执行查询(或多个查询)并返回结果?或者一次抓取大约200条记录,并将数据“分块”添加到OLV小部件中
提前谢谢你。-麦克风 --更新--
我已经检查过了,接受的答案没有返回任何内容,或者仍然锁定了GUI(不确定是什么导致了差异)。我想将创建的线程数量最多限制在5个左右 --新更新--
我对filter函数做了一些修改。您可能不想立即将整个数据库加载到内存中。这通常是个坏主意。因为ObjectListView是ListCtrl的包装器,所以我建议使用底层小部件的虚拟版本。该标志为wx.LC_VIRTUAL。以wxPython演示为例,但基本上是通过虚拟方法OnGetItemText()、OnGetItemImage()和OnGetItemAttr()按需加载数据。请注意,这指的是ListCtrl方法……在OLV land中可能会有所不同。无论如何,我知道OLV版本被称为VirtualObjectListView,其工作方式大致相同。我很确定下载的源代码中有一个示例。好的,我终于设法让查询在线程中运行,并能够在标准ObjectListView中显示结果。我对答案作了一些修改 我将代码添加到我的主辅助脚本中,该脚本作为EW导入到我的输出面板中
由于我没有向查询传递参数,这些行已更改:
def start(self, params):
self.thread = threading.Thread(target=self.func, args=params)
到
在我的输出面板中,我改变了调用默认查询的方式,即返回25000条以上记录的查询。在我的输出面板的init中,我添加了self.worker=()作为占位符,并在运行默认查询的函数中:
def defaultView(self, evt):
self.worker = EW.ThreadWorker(EW.defaultQuery)
self.worker.start()
pub.sendMessage('update.statusbar', msg='Full query started.')
我还补充说:
def threadUpdateOLV(self):
time.sleep(10)
anOutput = self.worker.get_results()
self.dataOLV.SetObjects(anOutput)
pub.subscribe(self.threadUpdateOLV, 'thread.completed')
time.sleep(10)是在尝试一个错误后添加的,以获得完整的25000+结果,我发现10秒的延迟效果很好
最后,在默认查询的末尾,我在输出返回之前添加了PubSub send:
wx.CallAfter(pub.sendMessage, 'thread.completed')
return anOutput
session.close()
老实说,我相信有更好的方法来实现这一点,但就目前而言,它正服务于所需的目的。不过,我会努力找到更好的解决方案
谢谢-Mike S我相信我能够找到一个使用ObjectListView虚拟版本的示例,位于。我确实保存了运行该示例所需的文件,并且我承认,即使有100k行,它也确实比普通OLV小部件运行得更快。我将致力于切换到VirtualLolv,看看它是否有助于我目前的问题。我仍然希望找到一种使用线程从数据库中获取数据的方法,最好是以较小的段来获取数据,而不是一次获取全部数据。要从数据库中获取较小段的数据,需要更改SQL查询。您需要告诉它一次获取X行数。我会走这条路线,然后在用户滚动小部件时跟踪他们。当它们接近行的末尾时,执行另一个查询以获取另外一百行。或者只是写一个循环,在后台获取X行数并适当地更新小部件。因此,我将OLV小部件切换为虚拟,现在我仍在寻找解决我最初问题的方法。在线程中运行查询并检索结果以便小部件显示的方法。我已经找到了一些答案,可以让GUI在进程运行时保持可用,但我无法获得结果
def threadUpdateOLV(self):
time.sleep(10)
anOutput = self.worker.get_results()
self.dataOLV.SetObjects(anOutput)
pub.subscribe(self.threadUpdateOLV, 'thread.completed')
wx.CallAfter(pub.sendMessage, 'thread.completed')
return anOutput
session.close()