imperosol
imperosol

Reputation: 578

execute an async function concurrently

I'm trying to make a command for a discord bot which make the bot perform actions that can be very long. So I want to send a message to inform the user before each key step.

However, due to network limitations, sending a message can take time, therefore slowing even more the program.

working code

When I call function which return no value, it works perfectly fine the following way :

import discord
import requests
import asyncio
    
with requests.Session() as session:
    await asyncio.gather(
        ctx.send("Connecting to the server"),
        init_session(session)
    )

TypeError with a dictionnary

But, the problem is that later on, I use a fonction which returns a dictionnary :

result = await asyncio.gather(
    ctx.send("Connecting to the server"),
    get_dict(session)
)

Then, it gives me the following error : asyncio gather TypeError: unhashable type: 'dict'

RunTimeError with a Thread

I also tried to execute the send function in another thread :

t = threading.Thread(target=asyncio.run, args=[ctx.send("Getting result")])
t.start()

But then I have yet another error : RuntimeError: Task <Task pending name='Task-20' coro=<Messageable.send() running at [my discord library directory]> cb=[_run_until_complete_cb() at [my asyncio directory]\base_events.py:184]> got Future <Future pending> attached to a different loop

So I would be really thankful if someone know a better way.

Upvotes: 0

Views: 392

Answers (2)

A. Rodas
A. Rodas

Reputation: 20679

A dictionary is not a valid argument for asyncio.gather, since it requires a list of awaitable objects.

If you want to keep the get_dict function as it is currently defined, you have to wrap it into an awaitable object, i.e. using loop.run_in_executor:

loop = asyncio.get_running_loop()
result = await asyncio.gather(
    ctx.send("Connecting to the server"),
    loop.run_in_executor(None, get_dict, session)
)

Upvotes: 1

Jakob Sch&#246;dl
Jakob Sch&#246;dl

Reputation: 406

When you are using an async function, there are only certain return types allowed. Those types need to be "hashable". A hashable item cannot be edited directly (like a list or a dict), instead the stored data is constant (like in a tuple or an int) (see this answer).

Thus, one solution for your error can be to use another datatype for the get_dict-function (I guess you should rename the function in that case as well).

If you do not want to change too much and never change anything about your dictionary after creation, consider converting it to a hashable version before you return it.

Upvotes: 0

Related Questions