【问题标题】:Ways to reduce loading time of wxPython GUI减少 wxPython GUI 加载时间的方法
【发布时间】:2012-04-19 16:29:26
【问题描述】:
这个问题是我的问题Desktop GUI Loading Slow的延续。
我有一个用 wxPython 开发的桌面 GUI,它使用 sqlAlchemy 从数据库中获取许多记录查询。我将获取的记录放入 Python 字典并使用它填充 GUI。但是,由于我在后台读取数千个数据,所以 GUI 会卡住并且加载非常缓慢。现在的问题是:
- 是否应该为每个 sqlalchemy 数据提取查询创建单独的线程?如果答案是肯定的,那么 wx.callAfter() 是我必须关注的方法(对于每个查询)吗?如果有人提供示例/未经测试的代码或链接,那将会很有帮助。
- 还有其他方法可以在桌面 GUI 中实现延迟加载吗?
P.S.:请注意,这是我第一次做多线程和 wxPython。我是 Python/Django 的早期 Web 开发人员。另外,由于限制,我无法共享代码。
【问题讨论】:
-
查看this关于 wxPython 中的多线程的文章
标签:
python
multithreading
performance
wxpython
【解决方案1】:
您应该重新设计您的应用程序,以便数据加载部分和数据显示部分是分开的。在一个单独的线程中加载数据,该线程应该在您的应用程序中填充数据库模型,使用该模型填充 GUI,因此当应用程序加载时,GUI 将快速加载,但会在数据没有的地方显示“正在加载...”或类似的东西尚未加载。
另一种加快速度的方法是在需要查询之前不要运行查询,例如使用 get 方法将它们包装在一个类中,在 get 查询 DB 上,但所有这些都取决于上下文。
此外,如果 GUI 主要用于视图,那么您可以加载第一组小数据并将其他数据推送到用户必须通过某些菜单或选项卡的其他视图,这样您可以延迟加载直到需要它或在后台加载它们。
【解决方案2】:
有几种方法可以防止您的 GUI 挂起。当然,您可以执行多线程并将记录填充到全局字典中。但是您可能会遇到global interpreter lock (GIL),这可能无助于您的 GUI 的响应能力。
第一种选择是使用 GUI 工具包的事件驱动特性,并使用工具包提供的“超时”或“计时器”功能来调用一个函数,该函数每次调用时都会加载几条记录。 generator function 可以很好地解决这个问题。这可能是最容易实现的。一次可以加载多少条记录取决于机器的速度。我建议从一条记录开始,测量记录的加载量,并增加记录的数量,这样每次调用的时间不会超过 0.1 秒。
第二个是使用第二个进程来加载数据,然后将其以小块的形式发送到 GUI。使用单独的进程(使用multiprocessing 模块)的优点是您不会遇到 Python 的 GIL。请注意,此方法或多或少包含第一种方法,因为您仍然必须在 GUI 的事件循环中处理来自第二个进程的消息。
【解决方案3】:
您没有提到您使用哪些小部件将数据加载到其中,但如果您使用 wx.grid.Grid 或 ListCtrl,那么是的,在各个小部件的虚拟实现中存在一些“延迟”加载内容.例如,请参阅 wxPython 演示,了解可以容纳一百万个单元的网格。另请参阅 Anurag 的回答。您真的不需要一次加载所有数据。只需加载您可以实际显示的数据。然后您可以在用户滚动时加载更多内容(或在后台线程中预加载)。