python - 非阻塞 PyQT 作为一个额外的 GUI 可视化主进程的结果?
问题描述
我有一个主要过程来做一些事情(例如分析数据),它单独运行就好了。我还想制作一个简单的 GUI,使用PyQT5显示主要任务的结果。这个想法是 GUI 不应该干扰主进程,也就是说,如果我删除 GUI,它不应该对主进程造成任何问题。
主流程的代码很简单:
if __name__ == '__main__':
# initialize the object that performs the main task
tasker = Task()
# the graphical interface to visualize the result of tasker
gui = GUI(task) # GUI is a separate class that keeps a reference to tasker
# read the input data and do stuff on each new data instance
for f in listdir(inrepo):
data = read_new_data(f) # an utility function that reads new data from file
result = tasker.process(data) # tasker processes the new data and return some results
gui.update(data, result) # pass the data and result in the GUI to update it
GUI 类的代码很长,所以我这里只贴了几行,但我跳过的行只是为了创建小部件,没什么花哨的(我还没有连接任何事件)
class GUI(QApplication):
def __init__(self, tasker):
"""Initialize the application"""
super().__init__([])
self.tasker = tasker
# define the main window
self.window = QWidget()
self.window.setWindowTitle('GUI')
... # layout and components etc.
# show stuff
self.window.show()
self.exec()
所以我希望 GUI 完全独立于我的主进程。例如,如果我不再需要 GUI,我可以将 2 行gui = GUI(task)
和gui.update(data, result)
.
但是,问题是启动 GUI 会阻塞整个过程(我认为这是因为self.exec()
in GUI.__init__
,所以我的主进程无法继续循环数据。你能告诉我如何使 PyQT 非阻塞吗?它甚至可行吗? ?
我考虑过的一些选项:
线程:对于我的用例来说,它似乎比必要的复杂,它可能会使
task
从线程中引用实例变得困难。所有新的更新都task
应该反映在 GUI 中。如果我没记错的话,PyQT 的应用程序已经在一个线程上运行。所以多级线程可能会很麻烦。从另一个 Python 进程运行 GUI,通过共享文件夹进行通信:可能会导致高延迟。任何新数据和结果
task
都应立即反映在 GUI 中。写入文件然后从文件读取然后更新 GUI 会导致一些延迟。执行任务
GUI
:我可以使用一些超时事件来定期读取新数据并task
在它们上运行,但是一切都在很大程度上取决于 GUI,如果我不再需要 GUI,我不能只是将其注释掉。
任何建议都非常感谢!非常感谢!
解决方案
在 GUI 模式/控制台模式之间切换程序通常不像注释掉一些行那么简单。PyQt 尤其不允许您从主线程以外的任何地方运行 GUI 循环。不过,并不是所有的希望都落空了——这仅仅意味着您应该尽早决定您的程序是作为控制台应用程序还是作为 GUI 运行。
无需依赖注释掉代码,您可以在代码中创建一个“开关”,告诉您的代码如何执行。一种方法是在执行代码时检查命令行参数,例如:
import sys
if "--headless" in sys.argv[1:]: # checking the command-line arguments
run_code_without_gui()
else:
run_code_with_gui()
这样,执行您的代码python mycode.py --headless
将在没有 GUI 的情况下执行它(通过run_code_without_gui
函数),而执行python mycode.py
时将它作为 GUI 运行(通过run_code_with_gui
函数)。(虽然如果你真的要解析命令行参数,我推荐使用argparse 库)。
您甚至可以使分析代码与 GUI 代码完全分离,这样您就可以简单地运行一个函数,例如,analysis.py
在没有 GUI 的情况下执行,并让 GUI 在例如用户单击“分析”时调用完全相同的函数按钮。
另外需要注意的是,如果您的分析代码需要很长时间才能执行,它可能会无意中阻塞 GUI。在这种情况下,您应该在一个单独的“工作”线程中运行分析代码,该线程在单击“分析”按钮时产生,在执行时保持 GUI 响应。如果您希望分析无限期地与 GUI 一起运行,这可能是要走的路 - 在向用户显示 GUI 的同时创建用于分析的工作线程。
推荐阅读
- python-3.x - 为什么 json.dumps(json.loads(line)) 的长度比 line 大?
- c# - 如何使用 Nest 索引批量父子文档
- python - 将子图的大小与 gridspec 匹配
- teradata - 根据条件将多行转换为单行
- git - Git:如何将工作目录中的文件与早期提交中的相同文件进行比较?
- python - TclError: 没有显示名称,也没有 $DISPLAY 环境变量
- c# - 带有 Elasticsearch 7.1 的 NEST 7.0 alpha 2 中的 SortField
- chart.js - Chart.js 标签颜色定位在工具提示/图例中
- css - iOS Safari浏览器网站问题(没有高度?)
- sql - 在 SQL 上为函数创建快捷方式