Coroutines
Questions regarding coroutines and asyncio belong here.
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"])