Search code examples
pythonpython-3.xpython-asynciopython-telegram-bot

Asyncio + python-telegram-bot infinite thread loop problem


I'm using the python-telegram-bot library to create a Telegram bot that is able to answer messages and at the same time run background tasks every X seconds, and if a condition is met, send a Telegram message.

I'm facing a problem where every time the condition is met and the code sends a message, a new thread is created. I tried to isolate everything and came with this example code:

import asyncio
import logging
import threading
from telegram.ext import Application

TELEGRAM_TOKEN = "bot_token_here"
TELEGRAM_CHAT_ID = "telegram_chat_id_here"

async def work(application):
    while True:
        logging.info(f"=== There are: {threading.active_count()} threads. 1 ===")
        await application.bot.send_message(chat_id=TELEGRAM_CHAT_ID, text="test")
        logging.info(f"=== There are: {threading.active_count()} threads. 2 ===")
        await asyncio.sleep(5)

        threads = threading.enumerate()
        for thread in threads:
            try:
                logging.info(f"Thread name: {thread.name} - alive: {thread.is_alive()} - daemon: {thread.daemon}")
            except Exception as e:
                logging.error(f"Error: {e}")

def main()->None:
    application = Application.builder().get_updates_http_version('1.1').http_version('1.1').token(TELEGRAM_TOKEN).build()
    
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    loop.run_until_complete(work(application))
    loop.close()

if __name__ == "__main__":
    main()

The output looks like:

2023-08-11 09:41:55,328 - root - INFO -  === There are: 1 threads. 1 ===
2023-08-11 09:41:55,804 - root - INFO -  === There are: 2 threads. 2 ===
2023-08-11 09:42:00,811 - root - INFO -  Thread name: MainThread - alive: True - daemon: False
2023-08-11 09:42:00,812 - root - INFO -  Thread name: ThreadPoolExecutor-0_0 - alive: True - daemon: True
2023-08-11 09:42:00,812 - root - INFO -  === There are: 2 threads. 1 ===
2023-08-11 09:42:01,057 - root - INFO -  === There are: 3 threads. 2 ===
2023-08-11 09:42:06,063 - root - INFO -  Thread name: MainThread - alive: True - daemon: False
2023-08-11 09:42:06,063 - root - INFO -  Thread name: ThreadPoolExecutor-0_0 - alive: True - daemon: True
2023-08-11 09:42:06,063 - root - INFO -  Thread name: ThreadPoolExecutor-0_1 - alive: True - daemon: True
2023-08-11 09:42:06,063 - root - INFO -  === There are: 3 threads. 1 ===
2023-08-11 09:42:06,286 - root - INFO -  === There are: 4 threads. 2 ===
...

And so on...

If I remove the await asyncio.sleep(5) line I get:

2023-08-11 09:32:50,957 - root - INFO -  === There are: 1 threads. 1 ===
2023-08-11 09:32:51,268 - root - INFO -  === There are: 2 threads. 2 ===
2023-08-11 09:32:51,268 - root - INFO -  Thread name: MainThread - alive: True - daemon: False
2023-08-11 09:32:51,268 - root - INFO -  Thread name: ThreadPoolExecutor-0_0 - alive: True - daemon: True
2023-08-11 09:32:51,268 - root - INFO -  === There are: 2 threads. 1 ===
2023-08-11 09:32:51,403 - root - INFO -  === There are: 2 threads. 2 ===
2023-08-11 09:32:51,403 - root - INFO -  Thread name: MainThread - alive: True - daemon: False
2023-08-11 09:32:51,403 - root - INFO -  Thread name: ThreadPoolExecutor-0_0 - alive: True - daemon: True
2023-08-11 09:32:51,403 - root - INFO -  === There are: 2 threads. 1 ===
2023-08-11 09:32:51,502 - root - INFO -  === There are: 2 threads. 2 ===

So this time always 2 threads.

I need my work function to wait before the next execution, but then I get this infinite thread generator...

I also tested removing the send_message line instead and leave the asyncio.sleep(5) alone but it doesn't create new threads, only with the combination of the two functions.

Can anyone help me understand what am I doing wrong or if this is expected?


Solution

  • Answering my own question...

    After further testing, it seems that the problem was with the Python version used (3.7). I upgraded to 3.11 and the problem is now gone, it now just created one thread.