Reputation: 3
Below code runs well and does its job. However, when I exit the GUI, the python file does not finish processing.
When I run through pycharm debug run then force terminate the debug, I get the message "Process finished with exit code -1".
Could anyone help me to find what is causing this error?
from PyQt5 import uic
from PyQt5.QtWidgets import QWidget
from pybithumb import WebSocketManager
from PyQt5.QtCore import QThread, pyqtSignal
class OverViewWorker(QThread):
data24Sent = pyqtSignal(int, float, int, float, int, int)
dataMidSent = pyqtSignal(int, float, float)
def __init__(self, ticker):
super().__init__()
self.ticker = ticker
self.alive = True
def run(self):
wm = WebSocketManager("ticker", [f"{self.ticker}_KRW"], ["24H", "MID"])
while self.alive:
data = wm.get()
if data['content']['tickType'] == "MID":
self.dataMidSent.emit(int(data['content']['closePrice']),
## Deleted
else:
self.data24Sent.emit(int(data['content']['closePrice']),
## Deleted
def close(self):
self.alive = False
class OverviewWidget(QWidget):
def __init__(self, parent=None, ticker="BTC"):
super().__init__(parent)
uic.loadUi("resource/overview.ui", self)
self.ticker = ticker
self.ovw = OverViewWorker(ticker)
self.ovw.data24Sent.connect(self.fill24Data)
self.ovw.dataMidSent.connect(self.fillMidData)
self.ovw.start()
def fill24Data(self, currPrice, volume, highPrice, value, lowPrice, PrevClosePrice):
## Deleted
def fillMidData(self, currPrice, chgRate, volumePower):
## Deleted
def closeEvent(self, event):
self.ovw.close()
if __name__ == "__main__":
import sys
from PyQt5.QtWidgets import QApplication
app = QApplication(sys.argv)
ob = OverviewWidget()
ob.show()
exit(app.exec_())
Upvotes: 0
Views: 2345
Reputation: 104
In your code, the QThread.run() method enters a while True loop, which never allows any CPU time to execute the close method and change self.alive to False, therefore that loop never ends even though you emit the close signal from the QWidget.
You are then trying to quit a thread which is still running, and that gives you the -1 return code as your QThread is forcefully killed without finishing its tasks.
If you add the possibility to update the alive parameter from within the loop, you can get out of this issue, but it would need the QThread to access a parameter of the QWidget, which may not be what you want.
Moreover, using QThread.wait() method may help you for synchronizing, as it will forcefully delay the exit of your QWidget until ovw returns from run. Since your -1 return code may just be due to your QApplication exiting moments before the thread finishes, synchronizing the exits will alleviate that.
Here is an example of that based on your code :
from PyQt5 import uic
from PyQt5.QtWidgets import QWidget
from pybithumb import WebSocketManager
from PyQt5.QtCore import QThread, pyqtSignal
class OverViewWorker(QThread):
data24Sent = pyqtSignal(int, float, int, float, int, int)
dataMidSent = pyqtSignal(int, float, float)
def __init__(self, ticker, master):
super().__init__()
self.ticker = ticker
self.master = master
self.alive = True
def run(self):
wm = WebSocketManager("ticker", [f"{self.ticker}_KRW"], ["24H", "MID"])
while self.alive:
data = wm.get()
if data['content']['tickType'] == "MID":
self.dataMidSent.emit(int(data['content']['closePrice']),
## Deleted
else:
self.data24Sent.emit(int(data['content']['closePrice']),
## Deleted
self.get_alive_from_master()
# Do here anything you want in the thread before quitting.
def get_alive_from_master(self):
self.alive = master.ovw_alive
class OverviewWidget(QWidget):
def __init__(self, parent=None, ticker="BTC"):
super().__init__(parent)
uic.loadUi("resource/overview.ui", self)
self.ticker = ticker
self.ovw = OverViewWorker(ticker, self)
self.ovw.data24Sent.connect(self.fill24Data)
self.ovw.dataMidSent.connect(self.fillMidData)
self.ovw_alive = True
self.ovw.start()
def fill24Data(self, currPrice, volume, highPrice, value, lowPrice, PrevClosePrice):
## Deleted
def fillMidData(self, currPrice, chgRate, volumePower):
## Deleted
def closeEvent(self, event):
self.ovw_alive = False
self.ovw.wait()
if __name__ == "__main__":
import sys
from PyQt5.QtWidgets import QApplication
app = QApplication(sys.argv)
ob = OverviewWidget()
ob.show()
exit(app.exec_())
Upvotes: 1
Reputation: 4698
Qt application exits if last window closed, if there are running threads left, it terminates them. It can be overriden with app.setQuitOnLastWindowClosed(False)
. In that case you must call app.quit()
on thread finished
to terminate application.
Upvotes: 0