You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyQt5中pyqtSignal.emit()触发退出码-1073741819(0xC0000005)的排查与解决

PyQt5中QRunnable与QObject多继承导致崩溃及信号失效的问题

问题原因

  1. 多继承初始化错误:QRunnable并非QObject的子类,你的Launcher类同时继承两者,但__init__中仅通过super().__init__()调用了QRunnable的构造函数,完全没有初始化QObject。而pyqtSignal依赖QObject的元对象系统,未初始化的QObject会导致信号机制彻底失效,甚至引发内存访问冲突(错误码0xC0000005正是内存访问违规的表现)。
  2. 局部对象被提前回收:launcher是MainWindow.__init__中的局部变量,线程池启动后,Python的垃圾回收可能会提前销毁这个对象,进一步加剧信号无法触发或程序崩溃的问题。

解决方法

方法一:修正多继承的初始化逻辑

显式调用两个父类的构造函数,确保QObject被正确初始化,同时将launcher改为MainWindow的实例属性避免被回收:

import sys
from PyQt5.QtCore import QObject, QRunnable, pyqtSignal, QThreadPool
from PyQt5.QtWidgets import QMainWindow, QApplication


class Launcher(QRunnable, QObject):
    test_signal = pyqtSignal()

    def __init__(self):
        # 分别调用两个父类的构造函数
        QRunnable.__init__(self)
        QObject.__init__(self)

    def run(self):
        print("This will be printed!")
        self.test_signal.emit()


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        # 改为实例属性,避免被垃圾回收
        self.launcher = Launcher()
        self.launcher.test_signal.connect(self.sayHi)
        self.threadpool = QThreadPool()
        self.threadpool.start(self.launcher)

    def sayHi(self):
        print("Hi")


def main():
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

方法二:使用组合模式(推荐)

Qt官方更推荐用组合而非多继承来处理这类场景——单独创建一个承载信号的QObject子类,在QRunnable中引用它,从根源避免多继承的兼容性问题:

import sys
from PyQt5.QtCore import QObject, QRunnable, pyqtSignal, QThreadPool
from PyQt5.QtWidgets import QMainWindow, QApplication


# 单独定义信号载体类
class WorkerSignals(QObject):
    test_signal = pyqtSignal()


class Launcher(QRunnable):
    def __init__(self):
        super().__init__()
        # 组合信号对象
        self.signals = WorkerSignals()

    def run(self):
        print("This will be printed!")
        self.signals.test_signal.emit()


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        launcher = Launcher()
        launcher.signals.test_signal.connect(self.sayHi)
        self.threadpool = QThreadPool()
        self.threadpool.start(launcher)
        # 保留引用防止对象被回收
        self.launcher = launcher

    def sayHi(self):
        print("Hi")


def main():
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

说明

组合模式更符合Qt的设计哲学,因为Qt的非QObject子类(如QRunnable)通常不建议与QObject多继承,容易引发元对象系统的冲突或未定义行为。

内容的提问来源于stack exchange,提问作者Alrond Prime

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 19:05:23