I’m using python-telegram-bot library
I’m trying to create telegram bot that works like anki. It add word and translation from user to database and later ask user to write translation of the word. I’m trying to send the user words for which he should write a translation. I have problems with this.
In main.py I can’t run asynchronously application.run_polling() that run telegram bot and send_messages.setup(application.bot) from send_messages.py that run while true loop for sending words.
I was trying different ways to solve my problem like asyncio event loop or asyncio.create_task() but that don’t work.
The code below only runs send_messages.setup(application.bot) with while true loop and prevents application.run_polling() from executing
main.py
import logging
import os
import telegram.ext as tg_ext
from bot import handlers, send_messages
TOKEN = os.getenv('TOKEN')
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.INFO,
)
logger = logging.getLogger(__name__)
def main() -> None:
application = tg_ext.ApplicationBuilder().token(TOKEN).build()
handlers.setup_handlers(application)
send_messages.setup(application.bot)
application.run_polling()
if __name__ == '__main__':
main()
send_messages.py
import telegram.ext as tg_ext
import asyncio
from database import db
async def send_words(bot: tg_ext.Application.bot) -> None:
"""Sends words to the user to write a translation."""
while True:
words = db.get_words_to_remember()
for word in words:
word_eng = word[0].word
user = word[1]
await bot.send_message(
user.chat_id, f'Enter translation: {word_eng}')
db.change_is_waiting(user)
await asyncio.sleep(60)
def setup(bot: tg_ext.Application.bot) -> None:
asyncio.run(send_words(bot))
3
Answers
It could be solved by telegram.ext.JobQueue that allow to perform tasks periodically with a running telegram bot
Corrected code:
main.py
send_messages.py
It is not possible to run a function which is not
async
concurrently in the same thread. You need to either use a different thread to runapplication.run_polling()
or use aThreadPoolExecutor
, which in turn will use a different thread under the hood.See https://docs.python.org/3/library/threading.html for python
threading
docs and examples.See https://stackoverflow.com/a/51051980/4542928 for an example of
ThreadPoolExecutor
.IMO the overall design looks like it could be improved. Specifically I’m thinking of
ConversationHandler
– see also the example. This should allow you to send words to the user, wait for the translation, then send the next word etc.