Как запустить бесконечный цикл в программе?
Делаю программу - лаунчер для игры. Работаю частично в Qt Deisgner и в редакторе. Есть Label, который выводит статус и кол. игроков на двух серверах.
def retranslateUi(self, MainWindow):
import requests
from bs4 import BeautifulSoup
import time
import webbrowser
URLServerOne = "https://www.battlemetrics.com/servers/valheim/10846961"
ResponseServerOne = requests.get(URLServerOne)
SoupServerOne = BeautifulSoup(ResponseServerOne.content, 'html.parser')
PlayerStatusServerOne = SoupServerOne.select_one('.dl-horizontal :nth-child(8)').text
PlayerCountServerOne = SoupServerOne.select_one('.dl-horizontal :nth-child(4)').text
URLServerTwo = "https://www.battlemetrics.com/servers/valheim/10648280"
ResponseServerTwo = requests.get(URLServerTwo)
SoupServerTwo = BeautifulSoup(ResponseServerTwo.content, 'html.parser')
PlayerStatusServerTwo = SoupServerTwo.select_one('.dl-horizontal :nth-child(8)').text
PlayerCountServerTwo = SoupServerTwo.select_one('.dl-horizontal :nth-child(4)').text
self.label.setText(_translate("MainWindow", "Статус серверов: Valheim.by #1 - {0} - {1}\nValheim.by #2 - {2} - {3}".format(PlayerStatusServerOne, PlayerCountServerOne, PlayerStatusServerTwo, PlayerCountServerTwo)))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Хочу сделать бесконечный цикл, который каждые 15 минут будет обновлять счётчик онлайн на сервере:
def retranslateUi(self, MainWindow):
import requests
from bs4 import BeautifulSoup
import time
import webbrowser
import threading
while True:
URLServerOne = "https://www.battlemetrics.com/servers/valheim/10846961"
ResponseServerOne = requests.get(URLServerOne)
SoupServerOne = BeautifulSoup(ResponseServerOne.content, 'html.parser')
PlayerStatusServerOne = SoupServerOne.select_one('.dl-horizontal :nth-child(8)').text
PlayerCountServerOne = SoupServerOne.select_one('.dl-horizontal :nth-child(4)').text
URLServerTwo = "https://www.battlemetrics.com/servers/valheim/10648280"
ResponseServerTwo = requests.get(URLServerTwo)
SoupServerTwo = BeautifulSoup(ResponseServerTwo.content, 'html.parser')
PlayerStatusServerTwo = SoupServerTwo.select_one('.dl-horizontal :nth-child(8)').text
PlayerCountServerTwo = SoupServerTwo.select_one('.dl-horizontal :nth-child(4)').text
if PlayerStatusServerOne == "online":
PlayerStatusServerOne = "Онлайн"
if PlayerStatusServerOne == "offline":
PlayerStatusServerOne = "Оффлайн"
if PlayerStatusServerTwo == "online":
PlayerStatusServerTwo = "Онлайн"
if PlayerStatusServerTwo == "offline":
PlayerStatusServerTwo = "Оффлайн"
#print('25')
time.sleep(1)
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Valheim.by - Launcher"))
self.progressBar.setFormat(_translate("MainWindow", "%p%"))
self.commandLinkButton.setText(_translate("MainWindow", "Valheim.by - наш сайт"))
self.commandLinkButton_2.setText(_translate("MainWindow", "Discord сервер"))
self.commandLinkButton.clicked.connect(lambda: webbrowser.open_new_tab('https://valheim.by'))
self.commandLinkButton_2.clicked.connect(lambda: webbrowser.open_new_tab('https://discord.gg/XCA6bPp3qB'))
self.pushButton.setText(_translate("MainWindow", "В ИГРУ"))
self.label.setText(_translate("MainWindow", "Статус серверов: Valheim.by #1 - {0} - {1}\nValheim.by #2 - {2} - {3}".format(PlayerStatusServerOne, PlayerCountServerOne, PlayerStatusServerTwo, PlayerCountServerTwo)))
self.label_3.setText(_translate("MainWindow", "Статус загрузки:"))
self.label_4.setText(_translate("MainWindow", "Проверка завершена"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
t = threading.Thread(target=retranslateUi, args=())
t.start()
sys.exit(app.exec_())
Но программа не запускается, а в консоль print() выводит, то есть считай цикл работает.
Ответы (1 шт):
Накидал пример реализации класса потока для запуска в нем тяжелых операций и как можно связать его к GUI. И сделал рефакторинг названий переменных, чтобы они соответствовали PEP
Вообще, можно сделать универсальный класс потока. Текущий использует всю логику из вашего кода, но можно сделать так, чтобы URL к сайту передавался в конструкторе потока, тогда для каждого сервера нужно будет сделать свой объект потока (покажу пример ниже в PS.). Либо на класс потока передавать список адресов, а тот будет ходить по ним и по сигналу передавать адрес сайта и статус
Вам нужно будет создать объект потока, навесить его сигнал(ы) на методы, в которые будет значение передаваться и запустить поток.
Пример:
import time
import sys
import webbrowser
import requests
from bs4 import BeautifulSoup
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel
from PyQt5.QtCore import QThread, pyqtSignal
class CheckServerStatusThread(QThread):
about_status1 = pyqtSignal(str)
about_status2 = pyqtSignal(str)
def __init__(self, timeout=15 * 50):
super().__init__()
self.timeout = timeout
def run(self):
while True:
self.about_status1.emit('<Выполняю запрос к серверу>')
url_server_one = "https://www.battlemetrics.com/servers/valheim/10846961"
rs = requests.get(url_server_one)
soup = BeautifulSoup(rs.content, 'html.parser')
player_status_server_one = soup.select_one('.dl-horizontal :nth-child(8)').text
player_count_server_one = soup.select_one('.dl-horizontal :nth-child(4)').text
self.about_status2.emit('<Выполняю запрос к серверу>')
url_server_two = "https://www.battlemetrics.com/servers/valheim/10648280"
rs = requests.get(url_server_two)
soup = BeautifulSoup(rs.content, 'html.parser')
player_status_server_two = soup.select_one('.dl-horizontal :nth-child(8)').text
player_count_server_two = soup.select_one('.dl-horizontal :nth-child(4)').text
if player_status_server_one == "online":
player_status_server_one = "Онлайн"
elif player_status_server_one == "offline":
player_status_server_one = "Оффлайн"
if player_status_server_two == "online":
player_status_server_two = "Онлайн"
elif player_status_server_two == "offline":
player_status_server_two = "Оффлайн"
self.about_status1.emit(player_status_server_one)
self.about_status2.emit(player_status_server_two)
time.sleep(self.timeout)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.label = QLabel()
self.thread = CheckServerStatusThread()
self.thread.about_status1.connect(self.label.setText)
# Для второго аналогично указать своего получателя:
# self.thread.about_status2.connect(self.label.setText)
self.thread.start()
self.setCentralWidget(self.label)
if __name__ == "__main__":
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec())
Работа выглядит так:
И через несколько секунд:
PS.
Возможно, серверов на проверку будет становиться больше и чтобы не менять логику класса потока, можно его завязать на работу только с одним адресом, для двух и более адресов нужно будет только создать свои объекты-потоки:
class CheckServerStatusThread(QThread):
about_status = pyqtSignal(str)
def __init__(self, url: str, timeout=15 * 50):
super().__init__()
self.url = url
self.timeout = timeout
def run(self):
while True:
self.about_status.emit('<Выполняю запрос к серверу>')
rs = requests.get(self.url)
soup = BeautifulSoup(rs.content, 'html.parser')
player_status = soup.select_one('.dl-horizontal :nth-child(8)').text
# player_count = soup.select_one('.dl-horizontal :nth-child(4)').text
if player_status == "online":
player_status = "Онлайн"
elif player_status == "offline":
player_status = "Оффлайн"
self.about_status.emit(player_status)
time.sleep(self.timeout)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.label = QLabel()
self.thread = CheckServerStatusThread("https://www.battlemetrics.com/servers/valheim/10846961")
self.thread.about_status.connect(self.label.setText)
self.thread.start()
self.setCentralWidget(self.label)

