QThread在mac上的pyqtgraph中被破坏

Posted

技术标签:

【中文标题】QThread在mac上的pyqtgraph中被破坏【英文标题】:QThread destroyed in pyqtgraph on mac 【发布时间】:2014-04-29 07:28:51 【问题描述】:

我正在尝试在 MacOS X 上使用 Anaconda python 运行我找到的这个简单示例 here。

import pyqtgraph as pg
import time

plt = pg.plot()

def update(data):
    plt.plot(data, clear=True)

class Thread(pg.QtCore.QThread):
    newData = pg.QtCore.Signal(object)
    def run(self):
        while True:
            data = pg.np.random.normal(size=100)
            # do NOT plot data from here!
            self.newData.emit(data)
            time.sleep(0.05)

thread = Thread()
thread.newData.connect(update)
thread.start()

但我不断得到:

QThread: Destroyed while thread is still running

【问题讨论】:

【参考方案1】:

您的程序将立即退出,因为您在启动线程后没有给它任何可做的事情。您看到的错误是因为线程很惊讶主线程没有它就退出了。

解决方法:在脚本末尾添加QtGui.QApplication.exec_()。或者,如果您有 PyQt(不是 PySide),则可以改为从交互式 python 提示符运行。

【讨论】:

【参考方案2】:

pyqtgraph.plot 方法对我来说似乎有问题(无论如何,我无法让它产生任何有用的输出,但也许我做错了什么)。

但是,如果我创建一个PlotWidget 并“手动”设置应用程序,一切都会按预期工作:

import pyqtgraph as pg
import numpy as np
import time

app = pg.QtGui.QApplication([])
window = pg.QtGui.QMainWindow()
plot = pg.PlotWidget()
window.setCentralWidget(plot)
window.show()

def update(data):
    plot.plot(data, clear=True)

class Thread(pg.QtCore.QThread):
    newData = pg.QtCore.Signal(object)
    def run(self):
        while True:
            data = pg.np.random.normal(size=100)
            # do NOT plot data from here!
            self.newData.emit(data)
            time.sleep(0.05)

thread = Thread()
thread.newData.connect(update)
thread.start()

app.exec_()

【讨论】:

ekhumoro:请在另一个 SO 问题或 pyqtgraph 邮件列表中分享您使用 pg.plot() 的经验。 @Luke。我现在无法重现我之前的问题,所以我一定是做错了什么,不知何故。没关系...【参考方案3】:

当您调用QThread.start() 时,该函数会立即返回。会发生什么,

    线程 #1 - 创建新线程 #2 线程 #2 已创建 线程 #1 重新获得控制权并运行。 线程 #1 死亡或 thread 变量被 GC(垃圾收集器)清理 - 我假设第二种情况不应该发生

要解决这个问题,不要让主线程死掉。在它死之前,清理所有线程。

http://pyqt.sourceforge.net/Docs/PyQt4/qthread.html#wait

bool QThread.wait (self, int msecs = ULONG_MAX)

阻塞线程直到满足以下任一条件:

与此 QThread 对象关联的线程已完成执行(即,当它从 run() 返回时)。该函数将返回 如果线程已完成,则为 true。如果线程也返回 true 尚未开始。 time 毫秒已经过去。如果时间为 ULONG_MAX(默认值),则等待永远不会超时(线程必须从 run() 返回)。 如果等待超时,此函数将返回 false。

这提供了与 POSIX pthread_join() 类似的功能 功能。

所以,将thread.wait() 添加到您的代码中。

注意:您需要确保您的线程退出。照原样,它永远不会退出。

【讨论】:

他没有事件循环 关键是,你在退出之前加入线程。即使主事件循环退出,你也必须加入你的线程,否则你会冒他所问的风险 我明白你的意思。但是:如果事件循环已启动,那么似乎没有必要等待线程。我不确定为什么,因为在事件循环退出后线程继续运行.. 有一个竞争条件,线程已启动但其线程存储未初始化 - 这就是导致来自 Qt 的错误消息的原因。然而,在离开主执行之前不等待线程完成可能会导致其他地方出现问题。在我的回答中,我假设任何使用 Qt 的人都已经知道诸如 QCoreApplication::exec() 之类的事情。它只出现在每个代码示例中:)

以上是关于QThread在mac上的pyqtgraph中被破坏的主要内容,如果未能解决你的问题,请参考以下文章

带有 pyqtgraph 的 GUI 从不刷新

在 MAC 上使用 anaconda python 的 Pyqtgraph 给出 nib 错误

pyqtgraph:如何绘制时间序列(x 轴上的日期和时间)?

如何处理 QThread 上的事件?

如何在Python PyQt中中断QThread上的脚本执行?

pyqtgraph 自定义缩放问题