我用c ++编写了一个Qt应用程序,它嵌入了Python解释器并利用PyQt来允许用于数据分析的脚本化用户界面。 Python代码对数据进行一些计算并返回一个插入主应用程序的QWidget(包含各种图等)。
我想从Python生成一个新的QThread,以允许控制返回到c ++应用程序,这样繁重的计算就不会阻塞GUI运行的主线程。问题是,只要控制权返回到c ++应用程序,线程就会进入睡眠状态,直到再次以某种方式调用Python解释器,例如。 matplotlib图上的mouseover事件。我怀疑这是由于Python的GIL。
如何在控件传回嵌入式应用程序后继续运行从Python创建的QThread?
我正在使用以下代码进行测试。嵌入应用程序调用test_thread()并将返回的容器添加到QTabwidget。线程仅在我在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
答案 0 :(得分:0)
由于GIL或Global Interpreter Lock,CPython是单线程的。你不能从python运行多于1个并发线程。
https://wiki.python.org/moin/GlobalInterpreterLock
Qt在这里没有阻止你,python是。这里唯一的解决方法是为您的工作者“线程”生成单独的python进程,然后使用IPC(套接字,共享内存等)在进程之间进行通信。 Qt为这些IPC机制提供接口。您只需要序列化进程间通信。
这假设您在询问并发性。关于其他事情,并编辑答案以澄清管辖权,
如何在控件传回嵌入式应用程序后继续运行从Python创建的QThread?
这是嵌入式应用程序的100%。允许python解释器 继续由嵌入应用程序运行。如果嵌入应用程序不允许python继续运行,那么任何绕过它的尝试都会导致问题。