python – the windowed application starts "Not responding" and freezes when transferring big data while the interface is running

Question:

There is a function (LoadData) for loading big data (taken from the database (SQlite)) into a text file ( fout ) with filling in the corresponding indicator ( self.ui.progressBar ). When the function is executed, the window application starts "Do not respond" and freezes (since the cycle time is ~ 3 minutes, depending on the size of data ) while the cycle ( for line in data ) is executed. Accordingly, the indicator value is 0% all this time. What are the options for solving this problem?

def LoadData(self, data):
    nof = self.ui.lineEdit_22.text() + '.txt' #Имя файла вводит пользователь
    fout = open(nof, 'w')
    self.step = 0 #Значение индикатора
    percent = len(data)/100 #Количество строк в 1%
    coun = 0 #Счётчик строк
    for line in data:
        for i in range(10):
            fout.write(str(line[i]))
            fout.write(' ')
        fout.write('\n')
        coun = coun + 1
        if coun == percent:
            coun = 0
            self.step = self.step + 1
            self.ui.progressBar.setValue(self.step)
    fout.close()

Answer:

Start long process in QThread:

import sys
import time
from PyQt5 import QtCore, QtWidgets

class SlowTask(QtCore.QThread):
    updated = QtCore.pyqtSignal(int)
    running = False

    def __init__(self, *args, **kwargs):
        super(SlowTask, self).__init__(*args, **kwargs)
        self.percent = 0
        self.running = True

    def run(self):
        while self.running:
            self.percent += 1
            self.percent %= 100
            self.updated.emit(int(self.percent))
            time.sleep(0.1)

    def stop(self):
        self.running = False


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self.setupUi()

    def setupUi(self):
        self.setWindowTitle('Test')
        self.resize(446, 207)

        self.progressbar = QtWidgets.QProgressBar(self)
        self.progressbar.setGeometry(QtCore.QRect(40, 70, 381, 23))
        self.progressbar.setProperty('value', 0)

        self.btn_start = QtWidgets.QPushButton('Start', self)
        self.btn_start.setGeometry(QtCore.QRect(110, 110, 75, 23))
        self.btn_start.setEnabled(True)
        self.btn_start.clicked.connect(self.on_start)

        self.btn_stop = QtWidgets.QPushButton('Stop', self)
        self.btn_stop.setGeometry(QtCore.QRect(260, 110, 75, 23))
        self.btn_stop.setEnabled(False)
        self.btn_stop.clicked.connect(self.on_stop)

    def toggle_buttons(self):
        self.btn_start.setEnabled(not self.btn_start.isEnabled())
        self.btn_stop.setEnabled(not self.btn_stop.isEnabled())

    def on_update(self, data):
        self.progressbar.setValue(data)
#        if data == 99:
#            self.on_stop()

    def on_start(self):
        self.toggle_buttons()
        self.task = SlowTask(self)
        self.task.updated.connect(self.on_update)
        self.task.start()

    def on_stop(self):
        self.task.stop()
        self.progressbar.setValue(0)
        self.toggle_buttons()


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())
Scroll to Top