问题背景描述:项目程序涉及到机器学习,需要实现机器学习模型的寻参和训练,封装到应用程序中,由于模型训练需要较多时间,所以会出现程序打包成exe之后,触发模型训练之后会出现程序“无响应”的卡死现象,并且程序卡死之后会产生很多个新的相同窗口,而且实际上模型没有训练(程序本身在PycharmIDE中测试没有任何问题)
解决路径
考虑的解决方案思路如下:
- 使用多线程,启动新的线程来执行耗时的模型训练和寻参过程
pyqt中的多线程模块使用多线程模块QThread解决PyQt界面程序唉执行耗时操作时,程序卡顿出现的无响应以及界面输出无法实时显示的问题。用户使用工具过程中出现这些问题时会误以为程序出错,从而把程序关闭。这样,导致工具的用户使用体验不好。
参考Python GUI程序运行时,如果点击按钮运行了一个比较耗时的操作,那么界面会卡死提示未响应。原因是主进程执行耗时等待 - 在程序设计的时候考虑到各部分的耗时,将各个环节分开
- 前端增加提示,提示训练开始与结束已经可能会训练很久,增加对用户的友好性
上述修改都没有带来根本上的问题解决
最后通过单元测试,定位到模型寻参模块的代码,最终发现,在python-sklearn中使用的RandomizedSearchCV中设置了多线程寻参的模式,将多线程改成了单线程,将程序就可以正常运行了,只不过由于单线程寻参,寻找的过程时间变长了。
分析分析问题成因
Q:我的程序出现的问题是这样子的:就是在我点击开始模型训练的时候,程序就无响应了,同时它产生了很多个相同的程序界面,但是它实际上并没有开始训练模型,就卡在那里了
A:这种情况可能是由于程序在启动训练模型时,进入了一个死循环或者阻塞了主线程,导致程序无响应并且创建了多个相同的程序界面。
为了排除这个问题,您可以尝试在程序中添加一些调试信息来帮助您确定程序的执行过程中具体卡在了哪里,比如使用日志记录程序执行状态,或者在程序中添加调试语句。此外,您还可以尝试在程序启动训练模型之前添加一些提示信息或者进度条等界面元素,以便您更好地了解程序的执行情况。
如果您无法通过调试信息解决问题,可以尝试使用 Python 的多线程或异步编程技术,以避免阻塞主线程。另外,您也可以尝试使用 Python 的调试工具(如 pdb 或 PyCharm 的调试工具)来帮助您找到程序的问题所在。
Q:为什么阻塞了主线程就会创建多个相同的程序界面呢?
A:当程序阻塞主线程时,通常意味着主事件循环被阻塞,导致程序无法响应用户输入或者界面事件。在这种情况下,如果程序中有其他线程或进程正在运行,它们可能会继续执行,并且可能会创建新的界面或者窗口,导致出现多个相同的程序界面。
这种情况的具体原因可能是因为您的程序中某个长时间运行的任务阻塞了主线程,例如模型训练任务。当用户点击“开始模型训练”按钮时,程序会启动该任务,并将其放入主线程中执行。如果该任务的执行时间很长,主线程就会被阻塞,无法响应用户输入或者界面事件。在这种情况下,程序可能会继续运行其他任务(例如处理用户输入的代码),这些任务可能会创建新的界面或者窗口。
为了避免这种情况,您可以使用多线程或者异步编程技术,将长时间运行的任务放在一个单独的线程或进程中执行,以避免阻塞主线程。在 PyQT5 中,您可以使用 QThread 或者 QRunnable 来创建新的线程,从而在后台运行长时间任务。另外,您也可以使用 asyncio 库来实现异步编程,从而在后台运行长时间任务,而不会阻塞主线程。
如果您想了解如何在 PyQt5 中使用多线程或异步编程技术来避免阻塞主线程的问题,可以搜索以下关键词:
- PyQt5 threading
- PyQt5 QThread
- PyQt5 QRunnable
- PyQt5 async programming
- Python threading
- Python asyncio