0

Here's what I want to do.

I have multiple asynchronous functions and a separate asynchronous function let's say main. I want to call this main function with every other function I call.

I'm using this structure in a telegram bot, and functions are called upon a certain command. But I want to run main on any incoming message including the messages with commands as mentioned above where another function is also called. So in that case, I wanna run both (first command specific function then main function)

I believe this can be done using threading.RLock() as suggested by someone, but I can't figure out how.

What's the best approach for this?

1 Answers1

0

You could use aiotelegram in combination with asyncio's create_task().

While Threads can also do the job, they don't seem to be as good as asynchronous execution.

You can choose any telegram framework that provides an async context like Bot.run() does in aiotelegram, or you can even implement your own API client, just make sure you run on an asynchronous (ASGI) context.

The main idea then is to call asyncio.create_task() to fire up the main() function in parallel with the rest of the function that runs the Telegram Bot command.

Here's an example (note I've use my_main() instead main()):

import asyncio
from aiotg import Bot, Chat

bot = Bot(api_token="...")

async def other_command():
    #Replace this with the actual logic
    await asyncio.sleeep(2)

async def my_main():
    # Replace this with the actual parallel task
    await asyncio.sleep(5)

@bot.command(r"/echo_command (.+)")
async def echo(chat: Chat, match):
    task = asyncio.create_task(my_main())
    return chat.reply(match.group(1))

@bot.command(r"/other_command (.+)")
async def other(chat: Chat, match):
    task = asyncio.create_task(my_main())
    result = other_command()
    return chat.reply(result)

bot.run()

It is important to know that with this approach, the tasks are never awaited nor checked for their completion, so Exceptions or failed executions can be difficult to track, as well as any result from main() that needs to be kept. A simple solution for this is to declare a global dict() where you store the Task(s), so you can get back to them later on (i.e. with a specific Telegram Command, or running always within certain existing Telegram Commands).

Whatever logic you decide to keep track of the tasks, you can check if they're completed, and their results, if any, with Task.done() and Task.result(). See their official doc for further details about how to manage Tasks.

castel
  • 158
  • 3
  • 9
  • I'm already using a python framework called "Pyrogram". But I need to use one function with 100s of other functions, with your way, it'll be too lengthy as I believe there are easier ways for sure – Mystery Boy Apr 11 '21 at 06:44