I have read a lot on threads, but I really need help with this one: I have a PyQt Main GUI that runs an optimization with scipy.minimize... As I cannot not make an example of this I use a "placeholder" process to show what my problem is.
I want to let the Main GUI remain stoppable by the User, if the Process takes too long to give a result. My working example is this one, where I use an integration with sympy
import sympy as sp
import numpy as np
import matplotlib.pyplot as plt
import time, sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class IntegrationRunner(QObject):
'Object managing the integration'
def __init__(self):
super(IntegrationRunner, self).__init__()
self._isRunning = True
def longRunning(self):
# reset
if not self._isRunning:
self._isRunning = True
print("preparing Integration")
#this is known to be time consuming and returning not the right integral
#this is a placeholder for a "time consuming" operation that sould
#be handled by a thread outside the main GUI
#imagine an optimization process or any other time consuming operation
#that would freeze the Main GUI
t=sp.symbols('t')
exp=sp.sqrt((3*t+1)/t)
sol=sp.integrate(exp,t)
print(sol)
print('finished...')
def stop(self):
self._isRunning = False
#this is displayed when the "stop button" is clicked
#but actually the integration process won´t stop
print("Integration too long - User terminated")
class SimulationUi(QDialog):
'PyQt interface'
def __init__(self):
super(SimulationUi, self).__init__()
self.goButton = QPushButton('Run Integration')
self.stopButton = QPushButton('Stop if too long')
self.layout = QHBoxLayout()
self.layout.addWidget(self.goButton)
self.layout.addWidget(self.stopButton)
self.setLayout(self.layout)
self.simulThread = QThread()
self.simulThread.start()
self.simulIntegration = IntegrationRunner()
self.simulIntegration.moveToThread(self.simulThread)
#self.simulIntegration.stepIncreased.connect(self.currentStep.setValue)
# call stop on Integr.Runner from this (main) thread on click
self.stopButton.clicked.connect(lambda: self.simulIntegration.stop())
self.goButton.clicked.connect(self.simulIntegration.longRunning)
if __name__ == '__main__':
app = QApplication(sys.argv)
simul = SimulationUi()
simul.show()
sys.exit(app.exec_())
After clicking the "start" button and the "stop" button before the integration stops automatically i get this output:
>>preparing Integration
>>Integration too long - User terminated
>>Integral(sqrt((3*t + 1)/t), t)
>>finished...
This isn´t exactly my problem but I want to understand how I can use a thread where I can put time consuming calculations and stop them in order to try other "parameters" or "initial guesses" when using something like Scipy Minimize Is it even possible to stop an iterative function from "outside" and restart it without getting into "non responding"? Any help to improve here is appreciated. I took these example here as a guideline how-to-signal-from-a-running-qthread-back-to-... and pastebin