This concise article is about a common issue related to asynchronous programming in Python.
The Problem
When using async/await
in Python, you might confront this error:
RuntimeWarning: coroutine 'something' was never awaited
If this happens, it seems that you’re trying to use asyncio
to run asynchronous code, but you’re not awaiting the coroutines properly.
A coroutine is a function that is declared with async def
and can use await
to suspend its execution until another coroutine is done. When you call a coroutine, it doesn’t run immediately, but returns a coroutine object that you need to await or schedule in an event loop.
The error message you’re getting means that you have created a coroutine object, but you didn’t await it or run it in an event loop, so it never executed. This can cause unexpected behavior or memory leaks in your program. The code snippet below is a simplified, typical example of this case:
import asyncio
async def hello():
# wait for one second
await asyncio.sleep(1)
print("Hello, welcome to Sling Academy!")
hello()
Let’s see how we can fix this code in the next section.
Solutions
You have more than one option to get rid of the mentioned error.
Running the coroutine as the main entry point of your program
This approach uses asyncio.run()
to run the coroutine as the main entry point of your program. This means that you don’t need to define another coroutine function, but you just pass the coroutine object to asyncio.run()
.
The code example in the previous section can be fixed like this:
import asyncio
async def hello():
# wait for one second
await asyncio.sleep(1)
print("Hello, welcome to Sling Academy!")
asyncio.run(hello())
Output:
Hello, welcome to Sling Academy!
This option is good if you only have one coroutine to run and you don’t need to do anything else in your program.
Using await inside another coroutine
The point here is to use await
inside another coroutine. This means that you have to define another function with async def
and use await before calling hello()
.
import asyncio
async def hello():
# wait for one second
await asyncio.sleep(1)
print("Hello, welcome to Sling Academy!")
async def main():
# wait for hello() to finish
await hello()
# Run the main() coroutine
asyncio.run(main())
This option is good if you want to run the coroutines sequentially, one after another.
Using asyncio.create_task()
In case you want to run multiple coroutines at the same time, without blocking each other, this is the way to go. The idea here is to use asyncio.create_task()
to schedule the coroutine in the current event loop and run it concurrently with other coroutines.
Example:
import asyncio
async def hello():
# wait for one second
await asyncio.sleep(1)
print("Hello, welcome to Sling Academy!")
async def main():
tasks = [
asyncio.create_task(hello()),
asyncio.create_task(hello()),
asyncio.create_task(hello()),
]
await asyncio.gather(*tasks)
# Run the main() coroutine
asyncio.run(main())
That’s it. Happy coding & enjoy your day!