When integrating background processing into a PyQt5 application, instantiating QThread inside a local scope—such as a button-click handler—often triggers intermittent crashes or segmentation faults. The underlying cause is Python’s garbage collector reclaiming the QThread wrapper object once the local variable goes out of scope, even though the native thread is still executing.
To keep the thread alive, bind the instance to a long-lived parent object, typically the main window. The following example constructs the interface programmatically and retains the worker reference via self:
import sys
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import QApplication, QMainWindow, QTextEdit, QPushButton
class ComputationTask(QThread):
result_ready = pyqtSignal(str)
def __init__(self, identifier):
super().__init__()
self.identifier = identifier
def run(self):
total = 0
for i in range(1800000000):
total += i
self.result_ready.emit(f"Task {self.identifier} finished with total {total}")
class PrimaryWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("QThread Lifetime Example")
self.resize(500, 320)
self.output_area = QTextEdit(self)
self.output_area.setGeometry(40, 30, 320, 220)
self.launch_button = QPushButton("Execute", self)
self.launch_button.setGeometry(400, 40, 80, 30)
self.launch_button.clicked.connect(self._start_background_work)
# Preserve the thread as an instance attribute to prevent GC destruction
self.background_job = ComputationTask("Alpha")
self.background_job.result_ready.connect(self._display_output)
def _start_background_work(self):
if not self.background_job.isRunning():
self.background_job.start()
def _display_output(self, text):
current = self.output_area.toPlainText()
self.output_area.setPlainText(f"{current}\n{text}")
if __name__ == "__main__":
app = QApplication(sys.argv)
win = PrimaryWindow()
win.show()
sys.exit(app.exec_())
Storing the thread in self.background_job ensures the Python object persists for the entire execution window. When mulitple independent workers are reuqired, maintain them in a collection and prune entries only after receiving their finished signal.