LCsa
LCsa

Reputation: 657

Start telegram bot in separate thread

I have a process that should accept requests from two different sources. It is not important, what those requests are, consider them simple string messages for instance. Requests can come from two sources and are filed into a PriorityQueue. The main process handles the requests in the queue. One of the two sources for requests is a telegram bot created by the python-telegram-bot package. Every source needs to run its "event" loop to provide requests. Thus, I want to launch them in separate threads.

The (pseudo) code to show the intention would read as follows:

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

The telegram bot and corresponding requester look something like this:

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()

However, when running this, I receive the following error messsage:

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

It's the first time I use the telegram api and that I have multiple threads running in parallel. Plus, I have no experience in "web/network/etc." programming. Is it that simple? You shall not run a telegram bot in a separate thread! Or is there something very simple I am missing that would make a construct like mine possible?

Upvotes: 0

Views: 4032

Answers (2)

Ahmed Djamel
Ahmed Djamel

Reputation: 148

you can't run bot multiple time, this will make a conflict.

.start_polling()

should run only one time, so i think when you make it in multi-threading you will get a conflict.

Upvotes: 0

CallMeStag
CallMeStag

Reputation: 7020

Just some general hints on the usage of PTB (v13.x) in this context:

  • Updater.idle() is intended to keep the main thread alive - nothing else. This is because Updater.start_polling starts a few background threads that do the actual work but don't prevent the main thread from ending. If you have multiple things going on in the main thread, you'll probably have a custom "keep alive" and "shutdown" logic, so you'll likely not need Updater.idle() at all. Instead, you can just call Updater.stop() when you want it to shut down.
  • Updater.idle() allows you to customize which signals it sets. You can pass an empty list to not set any signal handlers.

Dislaimer: I'm currently the maintainer of PTB

Upvotes: 1

Related Questions