Как обновлять label в pyqt5 из другого процесса?

У меня есть 2 процесса:

  • один это парсер;
  • другой pyqt UI.

Парсер получает новые данные раз в 5 секунд. И эти данные нужно отображать и обновлять в label.

У меня не получается отображение и обновление данных для label.

import time
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QVBoxLayout, QMainWindow, QApplication, \
    QLabel, QWidget
from PyQt5.QtGui import QPixmap, QPalette
from PyQt5.QtCore import Qt, QObject, QThread
import sys
import random
from multiprocessing import Process


class UiMainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(362, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.listWidget = QtWidgets.QListWidget(self.centralwidget)
        self.listWidget.setGeometry(QtCore.QRect(10, 10, 336, 192))
        self.listWidget.setObjectName("listWidget")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(20, 270, 331, 200))
        self.label.setObjectName("label")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(10, 470, 141, 31))
        self.pushButton.setObjectName("pushButton")

        MainWindow.setCentralWidget(self.centralwidget)
        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Twitch"))
        self.pushButton.setText(_translate("MainWindow", "Закрыть"))





class Thread(QtCore.QThread):
    updateSignal = QtCore.pyqtSignal(str)

    def __init__(self, status, parent=None):
        super(Thread, self).__init__(parent)
        self.status = status


    def run(self):
        self.updateSignal.emit(f'{self.status}')
        self.msleep(1000)


class MainWindow(QMainWindow, UiMainWindow):
    def __init__(self, streamers_links, status):
        super().__init__()
        self.setupUi(self)

        self.streamers_links = streamers_links
        self.status = status

        self.pushButton.clicked.connect(self.exit)


        for links in range(len(self.streamers_links)):
            item = QtWidgets.QListWidgetItem()
            self.listWidget.addItem(item)
            __sortingEnabled = self.listWidget.isSortingEnabled()
            _translate = QtCore.QCoreApplication.translate
            item = self.listWidget.item(links)
            item.setText(_translate("MainWindow", self.streamers_links[links]))
            self.listWidget.setSortingEnabled(__sortingEnabled)





    def statusUpgrader(self, status):
        self.label.setText(status)

    def exit(self):
        #os.system("TASKKILL /F /IM chromedriver.exe")
        #os.system("TASKKILL /F /IM chrome.exe")
        raise SystemExit(1)

    def start_thread(self, status):
        self.thread = Thread(status)
        self.thread.updateSignal.connect(self.statusUpgrader)
        self.thread.start()


streamers_links = [
    'https://www.twitch.tv/rainbow6',
    'https://www.twitch.tv/r6esportsbr2',
    'https://www.twitch.tv/rainbow6fr',
    'https://www.twitch.tv/rainbow6de',
    'https://www.twitch.tv/rainbow6es',
    'https://www.twitch.tv/rainbow6jp'
]



def gui(streamer_links):
    app = QApplication(sys.argv)
    w = MainWindow(streamers_links, '')
    w.show()
    sys.exit(app.exec())


def starter(streamers_links):
    # допустим это парсер, который получает значения раз в 5 секунд
    for i in range(len(streamers_links)):
        checker = random.randint(1, 2)
        if checker == 1:
            status = streamers_links[i] + '  онлайн'
            print(status)
        else:
            status = streamers_links[i] + '  не в сети'
            print(status)
        MainWindow.start_thread(self, status)
        time.sleep(5)



if __name__ == '__main__':

    twitch_p = Process(target=starter, args=(streamers_links,))
    gui_p = Process(target=gui, args=(streamers_links,))
    twitch_p.start()
    gui_p.start()
    twitch_p.join()
    gui_p.join()

Ответы (1 шт):

Автор решения: S. Nick

Взаимодействовать с виджетами можно только в основном потоке.

Тяжелые задачи, например парсер, выполняются в дополнительном потоке.

Взаимосвязь между потоками осуществляется посредством Signals & Slots

Сигналы и слоты используются для связи между объектами. Механизм сигналов и слотов - это центральная особенность Qt и, вероятно, часть, которая больше всего отличается от функций, предоставляемых другими фреймворками...

import sys
import random
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.Qt import *

#import time
#from multiprocessing import Process


class UiMainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(362, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.listWidget = QtWidgets.QListWidget(self.centralwidget)
        self.listWidget.setGeometry(QtCore.QRect(10, 10, 336, 192))
        self.listWidget.setObjectName("listWidget")
        
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(20, 270, 331, 200))
        self.label.setObjectName("label")
        
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(10, 470, 141, 31))
        self.pushButton.setObjectName("pushButton")

        MainWindow.setCentralWidget(self.centralwidget)
        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Twitch"))
        self.pushButton.setText(_translate("MainWindow", "Закрыть"))


class Thread(QThread):
    updateSignal = QtCore.pyqtSignal(str, str)                              # !!!

    def __init__(self, streamers_links):
        super().__init__()
        self.streamers_links = streamers_links
        self.len_streamers_links = len(self.streamers_links)

    def run(self):
        num_link = 0
        self.msleep(1000)
        while True:
            # допустим это парсер, который получает значения раз в 5 секунд
            checker = random.randint(1, 2)
            if checker == 1:
                status = 'онлайн'
            else:
                status = 'не в сети'
                
            self.updateSignal.emit(self.streamers_links[num_link], status)  # !!!
            
            self.msleep(1000 * 5)   # 5 сек., установите нухную вам паузу 
            
            num_link += 1
            if num_link == self.len_streamers_links:
                num_link = 0


class MainWindow(QMainWindow, UiMainWindow):
    def __init__(self, streamers_links):
        super().__init__()
        self.setupUi(self)
        self.streamers_links = streamers_links 
        
        self.pushButton.clicked.connect(self.close)
        
        self.listWidget.setSelectionMode(QListWidget.SingleSelection)
        
        self.thread = Thread(self.streamers_links)
        self.thread.updateSignal.connect(self.selectItem)                 # !!!
        self.thread.start()

        for link in self.streamers_links:
            item = QtWidgets.QListWidgetItem(link)
            self.listWidget.addItem(item)

    def selectItem(self, _link, status):                                  # !!!
        self.label.setText(f'{_link}  ->  {status}')
        
        _items = self.listWidget.findItems(_link, Qt.MatchExactly)
        for item in _items: 
            item.setSelected(True)        
           

streamers_links = [
    'https://www.twitch.tv/rainbow6',
    'https://www.twitch.tv/r6esportsbr2',
    'https://www.twitch.tv/rainbow6fr',
    'https://www.twitch.tv/rainbow6de',
    'https://www.twitch.tv/rainbow6es',
    'https://www.twitch.tv/rainbow6jp'
]


if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = MainWindow(streamers_links)  
    w.show()    
    sys.exit(app.exec_())    

введите сюда описание изображения

→ Ссылка