Python — Использование QThread во встроенном приложении PyQt

Я написал приложение на Qt на c ++, которое встраивает интерпретатор Python и использует PyQt для обеспечения пользовательских сценариев для анализа данных. Код Python выполняет некоторые вычисления для данных и возвращает QWidget (содержащий различные графики и т. Д.), Который вставляется в основное приложение.

Я хотел бы создать новый QThread из Python, чтобы позволить элементу управления вернуться в приложение c ++, чтобы тяжелые вычисления не блокировали основной поток, в котором работает GUI. Проблема заключается в том, что как только управление возвращается обратно в приложение c ++, поток, по-видимому, переходит в спящий режим до тех пор, пока интерпретатор Python каким-то образом снова не будет вызван, например. событие наведения мыши на сюжете matplotlib. Я подозреваю, что это как-то связано с GIL Python.

Как я могу заставить QThread, созданный из Python, продолжать работать после того, как управление вернется в приложение для встраивания?

Я использую следующий код для тестирования. Приложение встраивания вызывает 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

3

Решение

CPython является однопоточным из-за GIL или Global Interpreter Lock. Вы не можете запустить более 1 параллельного потока из Python.

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

Qt не блокирует вас здесь, а Python. Единственный обходной путь — это создать отдельный процесс Python для вашего рабочего потока, а затем использовать IPC (сокеты, разделяемую память и т. Д.) Для взаимодействия между процессами. Qt предоставляет интерфейсы для этих механизмов IPC. Вам просто нужно будет сериализовать ваше межпроцессное взаимодействие.

Это предполагало, что вы спрашивали о параллелизме. Относительно чего-то другого и редактирования ответа для уточнения юрисдикции,

Как я могу заставить QThread, созданный из Python, продолжать работать после того, как управление вернется в приложение для встраивания?

Это 100% до вложения приложения. Интерпретатор Python должен будет разрешено продолжать запуск приложения встраивания. Если приложение для встраивания не позволяет Python продолжать работу, любые попытки обойти это приведут к проблемам.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]