Асинхронное программирование в PyQt5 python
Я изучаю библиотеку PyQt5 и Telrgram Client Api (telethone),
написал простенькую программу с дизайном, которая проверяет активную сессию.
Но вопрос более о выводе чем о проверке.
Программа сперва зависает, а после выводит статус всех аккаунтов.
Как сделать чтобы - программа не зависала и по ходу проверки выводила статус подключения одного аккаунта и т.д.
Сейчас она зависает и выводит статус сразу всех.
main.py
#include - telethone
from telethon.sync import TelegramClient, events
from telethon import connection
#GUI
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QLabel
#systems
import asyncio
import sys
import os
from os import path
#создания интерфейса
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(412, 230)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.labelnew = QLabel(self.centralwidget)
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setEnabled(True)
self.labelnew.setGeometry(QtCore.QRect(0, 30, 211, 50))
self.label.setGeometry(QtCore.QRect(0, 10, 411, 20))
font = QtGui.QFont()
font.setPointSize(14)
self.label.setFont(font)
self.label.setTabletTracking(False)
self.label.setAcceptDrops(False)
self.label.setLayoutDirection(QtCore.Qt.LeftToRight)
self.label.setAutoFillBackground(False)
self.label.setStyleSheet("color:rgb(208, 208, 208);")
self.label.setTextFormat(QtCore.Qt.PlainText)
self.label.setAlignment(QtCore.Qt.AlignCenter)
self.label.setWordWrap(False)
self.label.setObjectName("label")
self.label_2 = QtWidgets.QLabel(self.centralwidget)
self.label_2.setGeometry(QtCore.QRect(-4, -8, 421, 250))
self.label_2.setStyleSheet("background-color:black;")
self.labelnew.setStyleSheet("color:white;")
self.label_2.setObjectName("label_2")
self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
self.verticalLayoutWidget.setGeometry(QtCore.QRect(-1, 39, 421, 181))
self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.label_2.raise_()
self.label.raise_()
self.verticalLayoutWidget.raise_()
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
self.account_testing()
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label.setText(_translate("MainWindow", "Account Connactions"))
#функция проверки аккаунтов
def account_testing(self):
accounts_files = self.get_files()
for account in accounts_files:
client = TelegramClient(f"data/session/{account}.session" , 1 , "default")
client.connect()
label = QLabel(self.verticalLayoutWidget)
if not client.is_user_authorized():
label.setStyleSheet("padding-left:15px;color:rgb(255, 66, 69);")
label.setText("Accaount is not Connected")
else:
label.setText("Accaount is Connected")
label.setStyleSheet("padding-left:15px;color:rgb(95, 255, 92);")
self.verticalLayout.addWidget(label)
#функция получения файлов сессий
def get_files(self):
_path = "data/session/"
filelist = []
for root , dirs , files , in os.walk(_path):
for file in files:
if(file.endswith(".session")):
filelist.append( path.splitext( os.path.join(file))[0])
return filelist
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Я так думаю надо работать с асинхронными методами, но как подключить и как это сделать я не знаю. Пробовал найти разную информации, но ничего не работает.
Ответы (2 шт):
Должно помочь:
# include - telethone
from telethon.sync import TelegramClient, events
from telethon import connection
# GUI
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QLabel
# systems
import asyncio
import sys
import os
from os import path
import threading
# создания интерфейса
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(412, 230)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.labelnew = QLabel(self.centralwidget)
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setEnabled(True)
self.labelnew.setGeometry(QtCore.QRect(0, 30, 211, 50))
self.label.setGeometry(QtCore.QRect(0, 10, 411, 20))
font = QtGui.QFont()
font.setPointSize(14)
self.label.setFont(font)
self.label.setTabletTracking(False)
self.label.setAcceptDrops(False)
self.label.setLayoutDirection(QtCore.Qt.LeftToRight)
self.label.setAutoFillBackground(False)
self.label.setStyleSheet("color:rgb(208, 208, 208);")
self.label.setTextFormat(QtCore.Qt.PlainText)
self.label.setAlignment(QtCore.Qt.AlignCenter)
self.label.setWordWrap(False)
self.label.setObjectName("label")
self.label_2 = QtWidgets.QLabel(self.centralwidget)
self.label_2.setGeometry(QtCore.QRect(-4, -8, 421, 250))
self.label_2.setStyleSheet("background-color:black;")
self.labelnew.setStyleSheet("color:white;")
self.label_2.setObjectName("label_2")
self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
self.verticalLayoutWidget.setGeometry(QtCore.QRect(-1, 39, 421, 181))
self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.label_2.raise_()
self.label.raise_()
self.verticalLayoutWidget.raise_()
MainWindow.setCentralWidget(self.centralwidget)
#####################################################
threading.Thread(target=self.account_testing).start()
#####################################################
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label.setText(_translate("MainWindow", "Account Connactions"))
# функция проверки аккаунтов
def account_testing(self):
accounts_files = self.get_files()
for account in accounts_files:
client = TelegramClient(f"data/session/{account}.session", 1, "default")
client.connect()
label = QLabel(self.verticalLayoutWidget)
if not client.is_user_authorized():
label.setStyleSheet("padding-left:15px;color:rgb(255, 66, 69);")
label.setText("Accaount is not Connected")
else:
label.setText("Accaount is Connected")
label.setStyleSheet("padding-left:15px;color:rgb(95, 255, 92);")
self.verticalLayout.addWidget(label)
# функция получения файлов сессий
def get_files(self):
_path = "data/session/"
filelist = []
for root, dirs, files, in os.walk(_path):
for file in files:
if (file.endswith(".session")):
filelist.append(path.splitext(os.path.join(file))[0])
return filelist
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Я не могу проверить ваш пример, но один из вариантов предложу, попробуйте.
Мне не приглянулась ваша форма Ui_MainWindow(object) и предложу свою.
НИКОГДА НЕ ИЗМЕНЯЙТЕ код, сгенерированный Qt Designer, НИКОГДА.
Создайте другой класс, который наследуется от соответствующего виджета, и используйте созданный класс для его заполнения.
Тяжелые задачи должны выполняться в отдельном потоке.
import sys
import os
from os import path
#systems
#import asyncio
#include - telethone
from telethon.sync import TelegramClient, events
from telethon import connection
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QLabel
class WorkThread(QtCore.QThread):
threadSignal = QtCore.pyqtSignal(str, bool)
finished = QtCore.pyqtSignal(str)
def __init__(self, accounts_files):
super().__init__()
self.accounts_files = accounts_files
def run(self):
for account in self.accounts_files:
client = TelegramClient(f"data/session/{account}.session" , 1 , "default")
client.connect()
if not client.is_user_authorized():
# if not int(account[-1]) % 2:
user_authorized = False
else:
user_authorized = True
self.threadSignal.emit(account, user_authorized)
self.msleep(10)
# self.msleep(1000) # миллисекунд, имитируем длительную загрузку
self.finished.emit("Start thread")
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.thread = None
self.centralwidget = QtWidgets.QWidget()
self.centralwidget.setObjectName("centralwidget")
self.setCentralWidget(self.centralwidget)
self.label = QtWidgets.QLabel("Account Connactions",
self.centralwidget, alignment=QtCore.Qt.AlignCenter)
self.label.setObjectName("label")
self.textBrowser = QtWidgets.QTextBrowser()
self.textBrowser.setObjectName("textBrowser")
self.pushButton = QtWidgets.QPushButton('Start thread')
self.pushButton.setObjectName("pushButton")
self.pushButton.clicked.connect(self.go_clicked)
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
# self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.addWidget(self.label)
self.verticalLayout.addWidget(self.textBrowser)
self.verticalLayout.addWidget(self.pushButton, alignment=QtCore.Qt.AlignRight)
def go_clicked(self):
if self.thread is None:
accounts_files = self.get_files()
self.thread = WorkThread(accounts_files)
self.thread.threadSignal.connect(self.on_threadSignal)
self.thread.finished.connect(self.thread_finished)
self.thread.start()
self.pushButton.setText("Stop thread")
else:
self.thread.terminate()
self.thread = None
self.pushButton.setText("Start thread")
# функция получения файлов сессий
def get_files(self):
_path = "data/session/"
self.filelist = []
for root , dirs , files , in os.walk(_path):
for file in files:
if(file.endswith(".session")):
self.filelist.append( path.splitext( os.path.join(file))[0])
return filelist
# return [
# 'account1', 'account2', 'account3', 'account4',
# 'account5', 'account6', 'account7', 'account8',
# ]
def on_threadSignal(self, account, user_authorized):
cursor = self.textBrowser.textCursor()
cursor.movePosition(cursor.End)
if user_authorized:
cursor.insertHtml(f'''<br><b style="padding-left:15px;color:rgb(95, 255, 92);">
{account}: Accaount is Connected, code={user_authorized}
</b><br>''')
else:
cursor.insertHtml(f'''<br><b style="padding-left:15px;color:rgb(255, 66, 69);">
{account}: Accaount is not Connected, code={user_authorized}
</b><br>''')
self.textBrowser.ensureCursorVisible()
def thread_finished(self, text):
self.thread = None
self.pushButton.setText("Start thread")
StyleSheet = '''
#centralwidget {
background-color: rgba(35, 135, 135, 122);
}
#label {
font-size: 25px;
}
#textBrowser {
background-color: rgba(35, 135, 135, 222);
font-size: 15px;
}
#pushButton {
background-color: rgba(135, 135, 135, 122);
}
'''
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
app.setStyleSheet(StyleSheet)
w = MainWindow()
w.resize(500, 500)
w.show()
sys.exit(app.exec_())
