Я написал приложение на 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
CPython является однопоточным из-за GIL или Global Interpreter Lock. Вы не можете запустить более 1 параллельного потока из Python.
https://wiki.python.org/moin/GlobalInterpreterLock
Qt не блокирует вас здесь, а Python. Единственный обходной путь — это создать отдельный процесс Python для вашего рабочего потока, а затем использовать IPC (сокеты, разделяемую память и т. Д.) Для взаимодействия между процессами. Qt предоставляет интерфейсы для этих механизмов IPC. Вам просто нужно будет сериализовать ваше межпроцессное взаимодействие.
Это предполагало, что вы спрашивали о параллелизме. Относительно чего-то другого и редактирования ответа для уточнения юрисдикции,
Как я могу заставить QThread, созданный из Python, продолжать работать после того, как управление вернется в приложение для встраивания?
Это 100% до вложения приложения. Интерпретатор Python должен будет разрешено продолжать запуск приложения встраивания. Если приложение для встраивания не позволяет Python продолжать работу, любые попытки обойти это приведут к проблемам.
Других решений пока нет …