PyQt5 GUI长时间运行后冻结,后台进程仍正常运行的排查求助
问题描述
我正在开发一款基于PyQt5的桌面应用,该应用监听Kepware OPC服务器的数据,通过QPixmap在QLabel上显示最新的相机截图或画面,无用户交互操作,同时在后台完成数据库日志记录。
应用初始运行正常,GUI可定期更新,但运行一段时间(1小时至5-6小时不等)后,GUI出现冻结:QLabel停止更新,画面停留在最后一帧,但后台的数据库日志记录与计算仍正常进行,且无异常抛出(所有方法已包裹try-except块)。
已尝试的排查操作
- 确认PyInstaller打包的EXE具备所需的Kepware授权
- 怀疑QLabel.setPixmap()更新存在问题
- 考虑过内存泄漏或GUI线程缓慢终止,但无确凿证据
- 验证主线程无无限循环或阻塞代码
求助问题
为何QLabel.setPixmap()会静默停止更新,而程序其余部分仍正常运行?还需检查哪些内容?
同时,我怀疑以下代码片段是否存在隐患:
MainScreen类代码
import os import asyncio import datetime from qasync import asyncSlot from PyQt5 import uic from PyQt5.QtCore import Qt, QTimer from PyQt5.QtGui import QPixmap, QImage from PyQt5.QtWidgets import QMainWindow, QLabel from src.app_data import AppData from src.kepware_helper import KepwareHelper class MainScreen(QMainWindow): def __init__(self): try: super(MainScreen, self).__init__() current_dir = os.getcwd() print("current dir", current_dir) ui_file_path = os.path.join(current_dir, "assets", "gui.ui") uic.loadUi(ui_file_path, self) self.app_data = AppData() self.pixmap = QPixmap(os.path.join(current_dir, "assets", "initpixmap.png")) self.initialize_ui_elements() QTimer.singleShot(0, self.initialize_thread_definitions) except Exception as e: print("Error initializing MainScreen:", str(e)) self.app_data.get_log_helper().append_log(f"Error initializing MainScreen: {str(e)}") def closeEvent(self, event): try: self.update_status('Closing the application...') if self.kepware_helper: self.kepware_helper.unsubscribe() self.kepware_helper.disconnect_kepware() os._exit(0) return super().closeEvent(event) except Exception as e: print("Error closing MainScreen:", str(e)) self.app_data.get_log_helper().append_log(f"Error closing MainScreen: {str(e)}") def initialize_ui_elements(self): try: self.modelLabel = self.findChild(QLabel, "modelLabel") self.dummyLabel = self.findChild(QLabel, "dummyLabel") self.dateLabel = self.findChild(QLabel, "dateLabel") self.statusLabel = self.findChild(QLabel, "statusLabel") self.pixmapLabel = self.findChild(QLabel, "pixmapLabel") self.pixmapLabel.setPixmap(self.pixmap) self.pixmapLabel.setScaledContents(True) except Exception as e: print("Error initializing UI elements:", str(e)) self.app_data.get_log_helper().append_log(f"Error initializing UI elements: {str(e)}") @asyncSlot() async def initialize_thread_definitions(self): try: self.kepware_helper = KepwareHelper( self.update_status, self.update_pixmap, self.result_handler, self.update_model_label, self.update_dummy_label, ) await self.kepware_helper.connect_kepware() await self.kepware_helper.initialize_nodes() await self.kepware_helper.subscribe() except Exception as e: print("Error initializing threads:", str(e)) self.app_data.get_log_helper().append_log(f"Error initializing threads: {str(e)}") def update_pixmap(self, qImage = None): try: # Get the size of the settings image label if qImage: self.settingImageWidth = qImage.rect().width() self.settingImageHeight = qImage.rect().height() self.pixmap = QPixmap.fromImage(qImage) self.settingLastImage = qImage else: self.pixmap = QPixmap() self.pixmap.fill(Qt.transparent) original_pixmap = self.pixmap original_width = original_pixmap.width() original_height = original_pixmap.height() label_width = self.pixmapLabel.width() label_height = self.pixmapLabel.height() if original_width == 0 or original_height == 0 or label_width == 0 or label_height == 0: self.pixmapLabel.clear() return aspect_ratio = original_width / original_height if label_width / label_height > aspect_ratio: new_width = int(label_height * aspect_ratio) new_height = label_height else: new_width = label_width new_height = int(label_width / aspect_ratio) scaled_pixmap = original_pixmap.scaled(new_width, new_height, Qt.KeepAspectRatio) self.pixmapLabel.setPixmap(scaled_pixmap) self.pixmapLabel.setScaledContents(True) except Exception as e: print("Error updating pixmap:", str(e)) self.app_data.get_log_helper().append_log(f"Error updating pixmap: {str(e)}") def update_status(self, message): try: self.statusLabel.setText(message) except Exception as e: print("Error updating status:", str(e)) self.app_data.get_log_helper().append_log(f"Error updating status: {str(e)}") def result_handler(self, result): try: if result: self.statusLabel.setText("Sonuç: Başarılı") else: self.statusLabel.setText("Sonuç: Başarısız") self.dateLabel.setText(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) except Exception as e: print("Error handling result:", str(e)) self.app_data.get_log_helper().append_log(f"Error handling result: {str(e)}") def update_model_label(self, model): try: if model and model != "": self.modelLabel.setText(str(model)) else: self.modelLabel.setText("Ürün Bekleniyor....") except Exception as e: print("Error updating model label:", str(e)) self.app_data.get_log_helper().append_log(f"Error updating model label: {str(e)}") def update_dummy_label(self, dummy_no): try: if dummy_no and dummy_no != "": self.dummyLabel.setText(str(dummy_no)) else: self.dummyLabel.setText("Ürün Bekleniyor....") except Exception as e: print("Error updating dummy label:", str(e)) self.app_data.get_log_helper().append_log(f"Error updating dummy label: {str(e)}") def convert_to_qImage(self, image): try: height, width, channel = image.shape bytesPerLine = 3 * width qImg = QImage(image.data, width, height, bytesPerLine, QImage.Format_RGB888) return qImg except Exception as e: print("Error converting to QImage:", str(e)) self.app_data.get_log_helper().append_log(f"Error converting to QImage: {str(e)}") return None
应用入口代码
app = QApplication(sys.argv) loop = QEventLoop(app) asyncio.set_event_loop(loop) main_screen = gui_control.MainScreen() main_screen.show() with loop: loop.run_forever()
内容的提问来源于stack exchange,提问作者Musa AKYUZ
相关产品推荐
相关产品推荐

