С Новым годом! Форум программистов, компьютерный форум, киберфорум
Python: GUI, графика
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.89/9: Рейтинг темы: голосов - 9, средняя оценка - 4.89
4 / 4 / 0
Регистрация: 07.03.2019
Сообщений: 249
PyQt5

Pyqt5+TelegramBot

25.03.2023, 16:30. Показов 2263. Ответов 20
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте! Подскажите, пожалуйста, как можно соединить Бота в Телеграме и Графический интерфейс в pyqt5?

Например: Создается окно с 2 кнопками "ВКЛ" и "ВЫКЛ", которые, непосредственно, отвечают за включение и выключение какой-либо функции (Например, функция, которая будет выводить в терминале: 1, 2, 3, 4, 5 и т.д.)

И создается меню в телеграм-боте с теми же двумя кнопками, отвечающими за ту же функцию с ее "включением" и выключением".

Можете, пожалуйста, привести пример подобной реализации?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
25.03.2023, 16:30
Ответы с готовыми решениями:

Все методы и атрибуты PyQt5.QtGui PyQt5.Qtwdigets и QtCore
На официальной документации модуля я не нашёл все методы и атрибуты PyQt5. может дадите источник со всем этим добром??? Буду вам очень...

PyQt5 Error while finding module specification for 'PyQt5.uic.pyuic' (ModuleNotFoundError: No module named 'PyQt
В общем поставил pyqt5 и python3.7 пишу в консоль python -m PyQt5.uic.pyuic Выдает ошибку Error while finding module specification for...

PyQt5
Помогите пожалуйста. Как мне сделать так, чтобы при введение 3 сторон, информация с 3 полей считывались из полей и высчитывался периметр...

20
 Аватар для kapbepucm
1566 / 739 / 321
Регистрация: 02.05.2020
Сообщений: 1,654
26.03.2023, 22:14
Бот может "жить" в отдельном потоке, получать стандартно через API телеги (или как там устроено) события выбора меню от собеседника и пересылать эту информацию в GUI используя стандартный механизм qt сигналов-слотов.
0
4 / 4 / 0
Регистрация: 07.03.2019
Сообщений: 249
27.03.2023, 02:02  [ТС]
kapbepucm, Я попробовал просто запустить участок кода: bot.polling - в отдельном потоке через threading.Thread

В принципе, все работает так, как мне нужно. Но вот как этот поток прервать?
0
 Аватар для kapbepucm
1566 / 739 / 321
Регистрация: 02.05.2020
Сообщений: 1,654
27.03.2023, 21:04
А как вы его (бота) останавливаете без GUI?
0
4 / 4 / 0
Регистрация: 07.03.2019
Сообщений: 249
27.03.2023, 23:27  [ТС]
kapbepucm, А как его остановить с GUI? Поделитесь, пожалуйста

Добавлено через 5 минут
В двух словах, у меня процесс с запуском бота (именно этот bot.polling) происходит в одном классе:

Python
1
2
3
4
5
6
7
8
9
10
11
12
        
       def proc_bot():
            threading.Thread(target=bot.polling, daemon=True).start()
            while True:
                time.sleep(1)
                if stop_thread is True:
                    bot.stop_polling()
                    break
 
 
       proc_bot1 = threading.Thread(target=proc_bot, daemon=True)
       proc_bot1.start()
При нажимании на кнопку запускается функция, в которой меняется флаг stop_thread на True. Ну а при возвращении в класс, где прописан код выше - бот работу не возобновляет
0
 Аватар для kapbepucm
1566 / 739 / 321
Регистрация: 02.05.2020
Сообщений: 1,654
28.03.2023, 22:01
Но в этом коде я наблюдаю аж 2 потока

Cуть суть такова, надо в цикле потока вызвать QCoreApplication.processEvents, что будет ловить события из GUI которые предназначены этому потоку (в данном случае некий сигнал завершения) Лучше будет использовать QThread вместо питонского threading.Thread

Сигнал завершения можно связать также с заменой флага stop_thread
0
 Аватар для kapbepucm
1566 / 739 / 321
Регистрация: 02.05.2020
Сообщений: 1,654
29.03.2023, 17:50
пример, изучайте
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import sys
from PyQt5.QtWidgets import QWidget, QApplication, QVBoxLayout, QPushButton
from PyQt5.QtCore    import QThread, pyqtSignal, Qt, QCoreApplication
 
class WorkerThread(QThread):
  def __init__(self):
    super().__init__()
    self.enabled = True
  def disableBot(self):
    print("я поток, принял сигнал завершения от GUI")
    self.enabled = False
  def run(self):
    print("я поток, запускаю свой главый цикл")
    while True:
      self.sleep(1)
      QCoreApplication.processEvents()
      if self.enabled:
        print("я поток, чтото делаю")
      else:
        print("я поток, вижу флаг завершения, тут можно вызвать bot.stop_polling()")
        break
 
class Window(QWidget):
  disableBot = pyqtSignal()
  def __init__(self):
    super().__init__(None)
    self.button = QPushButton()
    self.button.clicked.connect(self.changeState)
    self.button.clicked.connect(self.processBot)
    self.button.state = False
    self.changeState()
    l = QVBoxLayout()
    l.addWidget(self.button)
    self.setLayout(l)
  def changeState(self):
    self.button.state = not self.button.state
    if self.button.state:
      self.button.setText("запуск бота")
    else:
      self.button.setText("остановка бота")
  def processBot(self):
    if self.button.state:
      print("останавка бота")
      self.disableBot.emit()
      QCoreApplication.processEvents()
      self.workerThread.quit()
      self.workerThread.wait()
    else:
      print("запуск бота")
      self.workerThread = WorkerThread()
      self.disableBot.connect(self.workerThread.disableBot, type=Qt.QueuedConnection)
      self.workerThread.start()
 
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
Добавлено через 2 минуты
всё, что происходит в def run(self): это в отдельном потоке и туда передаётся сигнал завершения из потока GUI
1
Модератор
Эксперт Python
 Аватар для Fudthhh
2695 / 1601 / 513
Регистрация: 21.02.2017
Сообщений: 4,210
Записей в блоге: 1
30.03.2023, 15:41
kapbepucm, очень плохой пример...

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import telebot
from PySide2 import QtWidgets, QtCore
 
 
class Worker(QtCore.QThread):
    
    def __init__(self, parent: QtCore.QObject = None) -> None:
        QtCore.QThread.__init__(self, parent)
        self.bot = telebot.TeleBot("")
 
    def run(self) -> None:
        self.bot.polling()
 
    def stop(self) -> None:
        self.bot.stop_polling()
 
 
class Widget(QtWidgets.QWidget):
 
    def __init__(self, parent: QtWidgets.QWidget = None) -> None:
        QtWidgets.QWidget.__init__(self, parent)
 
        self.worker = Worker(self)
        self.worker.started.connect(self.on_worker_started)
        self.worker.finished.connect(self.on_worker_finished)
 
        self.label = QtWidgets.QLabel("Включение бота", self)
        self.checkBox = QtWidgets.QCheckBox(self)
        self.checkBox.clicked.connect(self.on_checkBox_clicked)
 
        self.gridLayout = QtWidgets.QGridLayout(self)
        self.gridLayout.addWidget(self.label, 0, 0)
        self.gridLayout.addWidget(self.checkBox, 0, 1)
 
    def on_checkBox_clicked(self, state: bool) -> None:
        self.checkBox.setDisabled(True)
        if state:
            self.worker.start()
        else:
            self.worker.stop()
    
    def on_worker_started(self) -> None:
        self.checkBox.setChecked(True)
        self.checkBox.setEnabled(True)
    
    def on_worker_finished(self) -> None:
        self.checkBox.setChecked(False)
        self.checkBox.setEnabled(True)
 
 
if __name__ == "__main__":
    app = QtWidgets.QApplication()
    w = Widget()
    w.show()
    app.exec_()
1
 Аватар для kapbepucm
1566 / 739 / 321
Регистрация: 02.05.2020
Сообщений: 1,654
30.03.2023, 18:12
Fudthhh, так это же (мой пример) не про бота, а как чтото передать в цикл потока. От бота там только название
0
963 / 718 / 276
Регистрация: 10.12.2016
Сообщений: 1,762
31.03.2023, 07:24
Цитата Сообщение от Fudthhh Посмотреть сообщение
def __init__(self, parent: QtCore.QObject = None) -> None:
        QtCore.QThread.__init__(self, parent)
        self.bot = telebot.TeleBot("")
а как сюда message_handler приделать?
типа
Python
1
2
3
4
  # Handle '/start' and '/help'
    @bot.message_handler(commands=['help', 'start'])
    def send_welcome(message):
        bot.reply_to(message, "Hi there, I am EchoBot")
0
290 / 205 / 68
Регистрация: 18.09.2019
Сообщений: 407
Записей в блоге: 58
31.03.2023, 10:34
Цитата Сообщение от kapbepucm Посмотреть сообщение
Python
1
2
3
4
5
6
7
8
9
10
  def run(self):
    print("я поток, запускаю свой главый цикл")
    while True:
      self.sleep(1)
      QCoreApplication.processEvents()
      if self.enabled:
        print("я поток, чтото делаю")
      else:
        print("я поток, вижу флаг завершения, тут можно вызвать bot.stop_polling()")
        break
У меня вызывает опасения вот это прокручивание цикла обработки событий из контекста дополнительного потока. Ведь сам цикл обработки событий крутится в контексте главного потока (GUI-потока). А тут им рулят из дополнительного. Что-то как-то небезопасно всё это на мой взгляд.
0
Модератор
Эксперт Python
 Аватар для Fudthhh
2695 / 1601 / 513
Регистрация: 21.02.2017
Сообщений: 4,210
Записей в блоге: 1
31.03.2023, 10:58
vic5710, вариаций много, но правильнее всего бот должен создаваться в отдельном файле в виде класса, а потом уже использоваться.

iamvic, согласен, вообще вызов QCoreApplication.processEvents() считаю костылем который не должен применяться.

Добавлено через 5 минут
vic5710, как вариант еще можно использовать не декораторы, а вызов метода бота на добавление обработчика, выглядит должен как то так: bot.add_message_handler()
0
963 / 718 / 276
Регистрация: 10.12.2016
Сообщений: 1,762
31.03.2023, 11:36
Fudthhh, iamvic,
Все запросы к Telegram Bot API должны осуществляться через HTTPS в следующем виде: https://api.telegram.org/bot<token>/НАЗВАНИЕ_МЕТОДА
https://core.telegram.org/bots/api
на фига козе баян?
минимальный пример для Qt
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
from PyQt5 import Qt
import requests
import json
import time
import config 
 
URL = 'https://api.telegram.org/bot'
 
class W(Qt.QWidget):
    def __init__(self):
        super().__init__()
        self.offset = 0
        self.chat_id = None
        self.edit = Qt.QTextBrowser()
        self.btn = Qt.QPushButton('Check')
        self.line = Qt.QLineEdit()
        grid = Qt.QGridLayout(self)
        grid.addWidget(self.edit,0,0,4,4)
        grid.addWidget(self.btn,4,0,1,1)
        grid.addWidget(self.line,4,1,1,3)
        self.btn.clicked.connect(self.get_updates)
        self.line.returnPressed.connect(self.send_message)
        
    def get_updates(self):
        res = requests.get(f'{URL}{config.TOKEN}/getUpdates?offset={self.offset}').json()
        if res.get('ok'):
            msg = res['result'][-1]
            self.edit.insertPlainText('update: ' + time.asctime() +'\n')
            self.edit.insertPlainText(json.dumps(msg,indent = 4) + '\n')
            self.offset = max(self.offset,msg['update_id'])
            self.chat_id = msg['message']['chat']['id']
        
    def send_message(self):
        txt = self.line.text()
        res = requests.get(f'{URL}{config.TOKEN}/sendMessage?chat_id={self.chat_id}&text={txt}')
        print(res.status_code)
        
 
if __name__ == '__main__':
    app = Qt.QApplication([])
    w = W()
    w.show()
    app.exec_()
хотите поллинг - включите таймер
0
Модератор
Эксперт Python
 Аватар для Fudthhh
2695 / 1601 / 513
Регистрация: 21.02.2017
Сообщений: 4,210
Записей в блоге: 1
31.03.2023, 13:26
vic5710, действительно, тогда уж чего мелочиться, весь код должен быть написан ассемблере...

Даже если использовать предложенный тобою вариант, то зачем использовать requests и json в qt, используй QtNetwork.QUdpSocket, и QtCore.QJsonDocument.
0
290 / 205 / 68
Регистрация: 18.09.2019
Сообщений: 407
Записей в блоге: 58
31.03.2023, 17:03
Цитата Сообщение от Fudthhh Посмотреть сообщение
iamvic, согласен, вообще вызов QCoreApplication.processEvents() считаю костылем который не должен применяться.
Я бы не был столь категоричен. Похоже, что использование
Python
1
QCoreApplication.processEvents()
связано с использованием в операторе
Python
1
self.disableBot.connect(self.workerThread.disableBot, type=Qt.QueuedConnection)
параметра
Python
1
type=Qt.QueuedConnection
А этот QueuedConnection вовсю используется дополнительными потоками, пользующими moveToThread(). А вот надо ли обложить это дело мьютексами или и так сойдёт - совершенно не понятно.
0
963 / 718 / 276
Регистрация: 10.12.2016
Сообщений: 1,762
31.03.2023, 17:28
Цитата Сообщение от Fudthhh Посмотреть сообщение
Даже если использовать предложенный тобою вариант, то зачем использовать requests и json в qt, используй QtNetwork.QUdpSocket, и QtCore.QJsonDocument.
не умножайте сущностей сверх необходимых
это самый стандарт для Qt приложения, беэ лишних наворотов.
0
Модератор
Эксперт Python
 Аватар для Fudthhh
2695 / 1601 / 513
Регистрация: 21.02.2017
Сообщений: 4,210
Записей в блоге: 1
31.03.2023, 17:30
iamvic, при написании достаточно больших приложений на Qt, которые работают с различными интерфейсами (блокирующее чтение QSerialPort, QTcpSocket, QUdpSocket), огромные модели (QAbstractItemModel, QTableModel практически на миллиарды строк и столько же колонок), я ни разу не использовал сие конструкцию. Я не спорю что она используется под капотом и это оправдано, но обычному разработчику сие вещь не нужна. Возможно я ошибаюсь, но я не могу представить себе случай (кроме не оптимизированного говнокода), в котором бы была необходимость использовать QCoreApplication.processEvents().

Добавлено через 1 минуту
vic5710, но почему то ты не хочешь использовать библиотеку telebot, и зачем то призываешь использовать requests для этих целей.
0
963 / 718 / 276
Регистрация: 10.12.2016
Сообщений: 1,762
31.03.2023, 17:40
Цитата Сообщение от Fudthhh Посмотреть сообщение
vic5710, но почему то ты не хочешь использовать библиотеку telebot, и зачем то призываешь использовать requests для этих целей.
это и есть лишняя сущность - городить обертки с лишними потоками и прочими декорациями к HTTP/GET/POST
0
 Аватар для kapbepucm
1566 / 739 / 321
Регистрация: 02.05.2020
Сообщений: 1,654
31.03.2023, 20:02
Цитата Сообщение от Fudthhh Посмотреть сообщение
согласен, вообще вызов QCoreApplication.processEvents() считаю костылем который не должен применяться.
А если у нас бесконечный while true (пусть это будет не бот, а чтото другое, где это уместно) туда же никогда ничего и не придёт из GUI без processEvents

Цитата Сообщение от iamvic Посмотреть сообщение
А тут им рулят из дополнительного. Что-то как-то небезопасно всё это на мой взгляд.
а чего бояться- оно только свои events обрабатывает, другие (не своего потока) оно не трогает, если я правильно это понимаю, конечно: "Calling this function processes events only for the calling thread" Ну и это ещё: "This function is thread-safe."
0
290 / 205 / 68
Регистрация: 18.09.2019
Сообщений: 407
Записей в блоге: 58
02.04.2023, 08:19
Цитата Сообщение от kapbepucm Посмотреть сообщение
а чего бояться- оно только свои events обрабатывает, другие (не своего потока) оно не трогает, если я правильно это понимаю
Я-то так никогда не делал, хотя QueuedConnection мне очень интересен, но повода не было его применить. Всё как-то так обхожусь:
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import sys
from PyQt5.QtWidgets import QWidget, QApplication, QVBoxLayout, QPushButton
from PyQt5.QtCore    import QThread, pyqtSignal, Qt, QCoreApplication
from PyQt5.QtCore import QMutex, QMutexLocker
 
class WorkerThread(QThread):
  def __init__(self):
    super().__init__()
    self.enabled = True
    self.thread_mutex = QMutex()
  def disableBot(self):
    print("я поток, принял сигнал завершения от GUI")
    with QMutexLocker(self.thread_mutex):
      self.enabled = False
  def run(self):
    print("я поток, запускаю свой главый цикл")
    while True:
      self.sleep(1)
#      QCoreApplication.processEvents()
      if self.enabled:
        print("я поток, чтото делаю")
      else:
        print("я поток, вижу флаг завершения, тут можно вызвать bot.stop_polling()")
        break
 
class Window(QWidget):
  disableBot = pyqtSignal()
  def __init__(self):
    super().__init__(None)
    self.button = QPushButton()
    self.button.clicked.connect(self.changeState)
    self.button.clicked.connect(self.processBot)
    self.button.state = False
    self.changeState()
    l = QVBoxLayout()
    l.addWidget(self.button)
    self.setLayout(l)
  def changeState(self):
    self.button.state = not self.button.state
    if self.button.state:
      self.button.setText("запуск бота")
    else:
      self.button.setText("остановка бота")
  def processBot(self):
    if self.button.state:
      print("останавка бота")
      self.disableBot.emit()
#      QCoreApplication.processEvents()
      self.workerThread.quit()
      self.workerThread.wait()
    else:
      print("запуск бота")
      self.workerThread = WorkerThread()
#      self.disableBot.connect(self.workerThread.disableBot, type=Qt.QueuedConnection)
      self.disableBot.connect(self.workerThread.disableBot)
      self.workerThread.start()
 
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
2
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
02.04.2023, 08:19
Помогаю со студенческими работами здесь

Pyqt5
Здравствуйте! Вопрос следующий-Имеем изображение. На этом изображении ставим точку. В зависимости от того, где ставим точку, используется...

PyQt5
Здравствуйте, столкнулся c проблемой, просьба помочь. Делаю программу с использованием библиотеки PyQt5, в которой открывается окно и после...

Pyqt5
Напишите программу с хорошо разработанным, разработанным и протестированным графическим интерфейсом, который может обрабатывать и...

Не работает PyQt5
Долго пытался найти решение данной проблемы, ничего не выходило. Когда я из PyQt5.QtWidgets пытаюсь импортировать QApplication, то...

Функции в pyqt5
С QTableWIdget всё было понятно, а с QTableView даже с функциями морока какая-то. То же самое делаю, но не работает. В классе окна задал...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути
Programma_Boinc 01.01.2026
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути Сочетание глобально распределённой вычислительной мощности и инновационных. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru