Skip to main content

Coroutines

Questions regarding coroutines and asyncio belong here.

note

This content has been taken directly from the documentation, and inherited from discord.py. It will most likely be rewritten in the future.

What is a coroutine?

A coroutine is a function that must be invoked with await or yield from. When Python encounters an await it stops the function's execution at that point and works on other things until it comes back to that point and finishes off its work. This allows for your program to be doing multiple things at the same time without using threads or complicated multiprocessing.

If you forget to await a coroutine then the coroutine will not run. Never forget to await a coroutine.

Where can I use await?

You can only use await inside async def functions and nowhere else.

What does "blocking" mean?

In asynchronous programming a blocking call is essentially all the parts of the function that are not await. Do not despair however, because not all forms of blocking are bad! Using blocking calls is inevitable, but you must work to make sure that you don't excessively block functions. Remember, if you block for too long then your bot will freeze since it has not stopped the function's execution at that point to do other things.

If logging is enabled, this library will attempt to warn you that blocking is occurring with the message: Heartbeat blocked for more than N seconds. See Setting Up Logging for details on enabling logging.

A common source of blocking for too long is something like time.sleep. Don't do that. Use asyncio.sleep instead. Similar to this example:

# Bad
time.sleep(10)

# Good
await asyncio.sleep(10)

Another common source of blocking for too long is using HTTP requests with the famous module Requests: HTTP for Humans™. While Requests: HTTP for Humans™ is an amazing module for non-asynchronous programming, it is not a good choice for asyncio because certain requests can block the event loop too long. Instead, use the aiohttp library which is installed on the side with this library.

Consider the following example:

# Bad
r = requests.get("http://aws.random.cat/meow")
if r.status_code == 200:
json = r.json()
await channel.send(json["file"])

# Good
async with aiohttp.ClientSession() as session:
async with session.get("http://aws.random.cat/meow") as r:
if r.status == 200:
json = await r.json()
await channel.send(json["file"])