0

Im trying to multithread async functions, one with input, could you please help me?

functions

@client.event
async def on_message(message):
    print(f"{message.author.name}: {message.content}")

@client.event
async def on_ready():
    while True:
        message=input("> ")

run code:

if __name__ == "__main__":
    try:
        client.run(token, bot=True)
    except:
        exit(1)
user13758241
  • 1
  • 1
  • 7
  • Please expand your answer to provide details on what you are having trouble with. – Philip Ciunkiewicz Jul 07 '20 at 17:25
  • what details do you mean? I have problem with threading because I dont know how to thread these two functions – user13758241 Jul 07 '20 at 17:28
  • You could tell us why these two specific functions, in particular, are presenting a problem with threading. – Paul Cornelius Jul 08 '20 at 00:06
  • because I cant use threading module since theres async function and discord.py that is running by client.run(token, bot=True), Im looking for alternative to threading, but if you manage to thread the on_message(message) function, youre welcome – user13758241 Jul 08 '20 at 07:29

3 Answers3

0

off topic: the default value for bot is true, so you can just do client.run(token)

on topic: async "replaces" threading, https://stackoverflow.com/a/27265877/10192011 also if you want to have a input in discord.py you should look into tasks

raizo
  • 144
  • 2
  • 7
0

Very late to the party but thought I'd share for any future readers.

Sync programming is where python goes line by line and executes every statement in order, while async programming is when you define multiple blocks of code and you set them up to run at a later time when the CPU has spare cycles.

The issue here is that you can run sync functions in an async context, and those lengthy sync tasks will block the thread, stopping also all other async tasks (hence their "blocking tasks" name).

input() is a synchronous blocking task that sits idly waiting for user input until the enter key is pressed, but since it is a blocking function it will stop all other asynchronous code, including discord.py.

What you could do is make use of a separate package, aioconsole, which, among other cool things, includes aioconsole.ainput(). This is entirely similar to input() but works asynchronously:

from aioconsole import ainput

@client.event
async def on_ready():
    while True:
        message = await ainput("> ")
        # do whatever

Do note that the prompt you pass to ainpput() will be printed at the very beginning, if something else (due to this being an asynchronous context) prints while the user hasn't pressed Enter yet, the prompt message will stay where it is (including anything the user has typed so far) and the new printed text added after it, which may result to very confusing interactions...

WillyJL
  • 3
  • 3
0

Using a non async def as the thread target and run the async def from the thread target is one of the solution. Like below.

Example:

async def log_pub(self):
    while 1:
        sleep(1)
        await self.Publish()
        #Break the loop based on event
        if thread_exit_event.is_set():
            break

def handleThread(self):
    asyncio.run(self.log_pub())
    
def startLogging(self):
    thread = threading.Thread(target=self.handleThread, args=())
    thread.start()
Sp7
  • 1
  • 2