简体   繁体   English

在嵌入式PyQt应用程序中使用QThread

[英]Using QThread in embedded PyQt application

I have written a Qt application in c++ which embeds the Python interpreter and makes use of PyQt to allow for scriptable user interfaces for data analysis. 我用c ++编写了一个Qt应用程序,它嵌入了Python解释器并利用PyQt来允许用于数据分析的脚本化用户界面。 The Python code does some computations on the data and returns a QWidget (containing various plots etc.) which gets inserted into the main application. Python代码对数据进行一些计算并返回一个插入主应用程序的QWidget(包含各种图等)。

I would like to spawn a new QThread from Python to allow control to return to the c++ application so that heavy computations do not block the main thread in which the GUI runs. 我想从Python生成一个新的QThread以允许控制返回到c ++应用程序,以便繁重的计算不会阻止GUI运行的主线程。 The problem is that as soon as control is returned back to the c++ application, the thread appears to go to sleep until the Python interpreter is somehow invoked again, eg. 问题是,只要控制权返回到c ++应用程序,线程就会进入睡眠状态,直到再次以某种方式调用Python解释器,例如。 a mouseover event on a matplotlib plot. matplotlib图上的mouseover事件。 I suspect this is somehow due to Python's GIL. 我怀疑这是由于Python的GIL。

How can I have a QThread created from Python continue to run after control passes back to the embedding application? 如何在控件传递回嵌入应用程序后继续运行从Python创建的QThread?

I am using the following code to test. 我正在使用以下代码进行测试。 The embedding application calls test_thread() and adds the returned container to a QTabwidget. 嵌入应用程序调用test_thread()并将返回的容器添加到QTabwidget。 The thread only executes as I generate mouse events over the matplotlib plot. 线程仅在我在matplotlib图上生成鼠标事件时执行。

import time

from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import pyqtSignal, pyqtSlot

from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas

app = QtGui.QApplication.instance()  

class Worker(QtCore.QObject):
    finished = pyqtSignal()

    def __init__(self):
        QtCore.QObject.__init__(self)

    def do_work(self):
        for i in range(0, 10):
            print 'worker running'
            time.sleep(1)

        self.finished.emit()


class Controller(QtCore.QObject):
    def __init__(self):
        QtCore.QObject.__init__(self)

        self.thread = QtCore.QThread()
        self.worker = Worker()
        self.worker.moveToThread(self.thread)
        self.worker.finished.connect(self.thread.quit)
        self.thread.started.connect(self.worker.do_work)
        self.thread.finished.connect(app.exit)

    def start_thread(self):
        self.thread.start()


class Container(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)

        self.controller = Controller()
        self.controller.start_thread()

        self.fig = Figure(dpi=72, facecolor=(1, 1, 1), edgecolor=(0, 0, 0))
        self.fig.add_subplot(111)
        self.canvas = FigureCanvas(self.fig)

        self.layout = QtGui.QVBoxLayout()
        self.layout.addWidget(self.canvas)

        self.setLayout(self.layout)


def test_thread():
    container = Container()
    return container

CPython is single threaded because of GIL or Global Interpreter Lock. 由于GIL或Global Interpreter Lock,CPython是单线程的。 You cannot run more than 1 concurrent thread from python. 你不能从python运行多于1个并发线程。

https://wiki.python.org/moin/GlobalInterpreterLock https://wiki.python.org/moin/GlobalInterpreterLock

Qt is not blocking you here, python is. Qt在这里没有阻止你,python是。 The only workaround here is to spawn separate python process for your worker "thread" then use IPC (sockets, shared memory, etc) to communicate between processes. 这里唯一的解决方法是为您的工作者“线程”生成单独的python进程,然后使用IPC(套接字,共享内存等)在进程之间进行通信。 Qt provides interfaces for these IPC mechanisms. Qt为这些IPC机制提供接口。 You will just have to serialize your interprocess communication. 您只需要序列化进程间通信。

This assumed you were asking about concurrency. 这假设您在询问并发性。 Regarding something else, and editing answer to clarify jurisdiction, 关于其他事情,编辑答案以澄清管辖权,

How can I have a QThread created from Python continue to run after control passes back to the embedding application? 如何在控件传递回嵌入应用程序后继续运行从Python创建的QThread?

This is 100% up to the embedding application. 这是嵌入式应用程序的100%。 The python interpreter must be allowed to continue to run by the embedding application. 必须允许python解释器继续由嵌入应用程序运行。 If the embedding application does not allow python to continue to run, then any attempts to circumvent this will result in problems. 如果嵌入应用程序不允许python继续运行,那么任何绕过它的尝试都会导致问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM