PyQt5: обработка исключений в Qthreads - PullRequest
0 голосов
/ 04 августа 2020

Я не могу понять исключения в QThreads. Рассмотрим этот пример:

from PyQt5 import QtCore, QtGui, QtWidgets
import time


class Worker(QtCore.QObject):
    @QtCore.pyqtSlot()
    def do_stuff(self):
        print("Hello from worker")
        time.sleep(2)
        raise Exception("worker crashed")

class Gui(QtWidgets.QWidget):
    def __init__(self):
        super(Gui, self).__init__()

        self.worker = Worker()
        self.thread = QtCore.QThread()
        self.worker.moveToThread(self.thread)
        self.thread.start()
        
        button = QtWidgets.QPushButton(text="do stuff in worker")
        button.clicked.connect(self.worker.do_stuff)
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(button)

        self.show()


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = Gui()
    app.exec_()

Gui создает объект Worker, перемещает его в QThread и запускает его. Рабочий объект может получать сигналы и обрабатывать их в собственном потоке, чтобы не блокировать Gui.

Однако, если внутри рабочего процесса возникает исключение, вся программа вылетает с (на windows) ошибкой STATUS_STACK_BUFFER_OVERRUN (0xC0000409). Кажется, что ожидаемое поведение с версии PyQt 5.5

В этой ситуации исправление, которое, как представляется, рекомендуется, - это перехватить исключения в работнике, возможно, послать сигнал обратно в Gui с некоторой информацией об исключении, и пусть это обработает. Это решение не кажется идеальным, так как для этого потребовалось бы обернуть каждый метод в worker с помощью некоторого механизма try / except.

Есть ли другое решение? Как правильно обрабатывать сбои в QThreads?

...