在单独的线程中启动电报机器人

问题描述 投票:0回答:2

我有一个流程应该接受来自两个不同来源的请求。这些请求是什么并不重要,例如将它们视为简单的字符串消息。请求可以来自两个来源并归档到

PriorityQueue
。主进程处理队列中的请求。请求的两个来源之一是由
python-telegram-bot
包创建的电报机器人。每个源都需要运行其“事件”循环来提供请求。因此,我想在单独的线程中启动它们。

显示意图的(伪)代码如下:

queue = PriorityQueue()
handler = RequestHandler(queue)
telegramRequester = TelegramRequester(queue)
anotherRequester = SomeOtherSourceRequester(queue)

telegramRequester.start()        # launches telegram bot polling/idle loop
anotherRequester.start()         # launches the loop of another request source
handler.handleRequestsLoop()     # launches the loop that handles incoming requests

电报机器人和相应的请求者看起来像这样:

class Bot:
    def __init__(self):
        self._updater = telegram.ext.Updater("my api token", use_context=True)
    
    def run(self):
        self._updater.start_polling(drop_pending_updates=True)
        self._updater.idle()

    def otherFunctions(self):
        # like registering commands, command handlers etc.
        # I've got my bot working and tested as I want it.


class TelegramRequester:
    def __init__(self, queue:RequestQueue) -> None:
        self._queue:RequestQueue = requestQueue
        self._bot = Bot()
        self._thread:threading.Thread = threading.Thread(target=self._bot.run)

    def start(self):
        if not self._thread.is_alive():
            self._thread.start()

但是,运行此程序时,我收到以下错误消息:

File "...\myscript.py", line 83, in run
    self._updater.idle()
File "...\env\lib\site-packages\telegram\ext\updater.py", line 885, in idle
    signal(sig, self._signal_handler)
File "C:\Program Files\aaaProgrammieren\Python\Python3_9\lib\signal.py", line 47, in signal
    handler = _signal.signal(_enum_to_int(signalnum), _enum_to_int(handler))
ValueError: signal only works in main thread of the main interpreter

这是我第一次使用 telegram api,并且我有多个线程并行运行。另外,我没有“网络/网络/等”方面的经验。编程。真有这么简单吗? 你不应该在单独的线程中运行电报机器人!或者我是否缺少一些非常简单的东西来使像我这样的构造成为可能?

python multithreading python-telegram-bot
2个回答
1
投票

关于在此上下文中使用 PTB (v13.x) 的一些一般提示:

  • Updater.idle()
    的目的是保持主线程处于活动状态 - 没有别的。这是因为
    Updater.start_polling
    启动了一些 background 线程,这些线程执行实际工作,但不会阻止主线程结束。如果主线程中正在进行多个操作,您可能会有一个自定义的“保持活动”和“关闭”逻辑,因此您可能根本不需要
    Updater.idle()
    。相反,当您希望它关闭时,您可以调用
    Updater.stop()
  • Updater.idle()
    允许您自定义它设置的信号。您可以传递一个空列表来不设置任何信号处理程序。

免责声明:我目前是 PTB 的维护者


0
投票

你不能多次运行机器人,这会产生冲突。

.start_polling()

应该只运行一次,所以我认为当你在多线程中进行时,你会遇到冲突。

© www.soinside.com 2019 - 2024. All rights reserved.