I have a program which compares to DB table values and i have created a GUI in PyQt5. I have created two threads one for querying each table and then program has to wait till two threads are completed. My code below
from PySide2 import QtWidgets
from PySide2 import QtGui
from PySide2 import QtCore
from Main_interface import Ui_mainWindow
import pandas as pd
class mainWindow(QtWidgets.QMainWindow, Ui_mainWindow):
sqlClicked1 = QtCore.Signal(str)
sqlClicked2 = QtCore.Signal(str)
def __init__(self, parent=None):
super(mainWindow, self).__init__(parent)
self.setupUi(self)
self.thread = QtCore.QThread(self)
self.thread.start()
self.obj = Worker()
self.obj.moveToThread(self.thread)
self.sqlClicked.connect(self.obj.runsql_MC)
self.sqlClicked1.connect(self.obj.runsql_IRI)
self.obj.error.connect(self.on_error)
def run_report(self):
sqlquery1 = "Select * from table1"
sqlquery2 = "Select * from table2"
df1 = self.sqlClicked1.emit(sqlquery1)
df2 = self.sqlClicked2.emit(sqlquery2)
self.sqlClicked1.finished.connect(self.on_finished)
self.sqlClicked2.finished.connect(self.on_finished)
print("SQL execution is done")
#Then i am calling function to compare two dataframes
class Worker(QtCore.QObject):
finished = QtCore.Signal()
result = QtCore.Signal(object)
@QtCore.Slot(str)
def runsql_MC(self, sqlquery_MC):
print("Thread1 is working")
try:
df1 = pd.read_sql(sql=sqlquery_MC, con=cnxn)
except:
traceback.print_exc()
else:
self.signals.result.emit(df1) # Return the result of the processing
finally:
self.signals.finished.emit() # Done
@QtCore.Slot(str)
def runsql_IRI(self, sqlquery_IRI):
print("Thread2 is working")
try:
df2 = pd.read_sql(sql=sqlquery_IRI, con=cnxn)
except:
traceback.print_exc()
else:
self.signals.result.emit(df2)
finally:
self.signals.finished.emit()
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
my_app = mainWindow()
my_app.show()
sys.exit(app.exec_())
self.sqlClicked1.emit(sqlquery1)
and self.sqlClicked2.emit(sqlquery2)
is calling corresponding threads runsql_MC()
and runsql_IRI
. Then I need to wait till two threads are completed to start comparison process. Currently its not happening.
Although your code is not an MRE, show your ignorance of various concepts.
The emission of a signal does not imply obtaining the data as a result since it will be sent asynchronously.
In your code even if you invoke 2 queries does not imply that each one runs on different threads since the worker lives in a single thread.
Your runsql_MC and runsql_IRI methods are redundant since they are a template of the same thing.
In addition to other errors such as that there is no object/signal called sqlClicked, you have not declared the object signals, etc.
The idea is to have a worker who lives in a different thread for each query, and create a class that handles the workers waiting for the data and eliminating when they have finished their work.
from functools import partial
import sqlite3
import pandas as pd
from PySide2 import QtCore, QtGui, QtWidgets
class Worker(QtCore.QObject):
finished = QtCore.Signal()
result = QtCore.Signal(object)
@QtCore.Slot(str)
def runsql(self, query):
cnxn = sqlite3.connect("test.db")
print("Thread1 is working")
try:
df1 = pd.read_sql(sql=query, con=cnxn)
except:
traceback.print_exc()
else:
self.result.emit(df1) # Return the result of the processing
finally:
self.finished.emit() # Done
class SqlManager(QtCore.QObject):
results = QtCore.Signal(list)
def __init__(self, parent=None):
super().__init__(parent)
self.workers_and_threads = {}
self.dataframes = []
def execute_queries(self, queries):
for query in queries:
thread = QtCore.QThread(self)
thread.start()
worker = Worker()
worker.result.connect(self.onResults)
worker.moveToThread(thread)
self.workers_and_threads[worker] = thread
# launch task
wrapper = partial(worker.runsql, query)
QtCore.QTimer.singleShot(0, wrapper)
@QtCore.Slot(object)
def onResults(self, result):
worker = self.sender()
thread = self.workers_and_threads[worker]
thread.quit()
thread.wait()
del self.workers_and_threads[worker]
worker.deleteLater()
self.dataframes.append(result)
if not self.workers_and_threads:
self.results.emit(self.dataframes)
self.dataframes = []
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.push_button = QtWidgets.QPushButton("Run Report")
self.push_button.clicked.connect(self.run_report)
self.setCentralWidget(self.push_button)
self.manager = SqlManager(self)
self.manager.results.connect(self.onResults)
@QtCore.Slot()
def run_report(self):
sqlquery1 = "Select * from table1"
sqlquery2 = "Select * from table2"
queries = [sqlquery1, sqlquery2]
self.manager.execute_queries(queries)
self.push_button.setEnabled(False)
@QtCore.Slot(list)
def onResults(self, dataframes):
print(dataframes)
self.push_button.setEnabled(True)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
my_app = MainWindow()
my_app.show()
sys.exit(app.exec_())