The asyncio.run_until_complete() method is very useful for running asyncio code, but it has some nuances worth understanding to use it effectively.
What run_until_complete Does
The
import asyncio
async def my_coro():
return "result"
result = asyncio.run_until_complete(my_coro())
print(result) # Prints "result"
This allows you to run a coroutine to completion without needing to manually create an event loop.
Common Pitfalls
However, there are two common pitfalls when using
1. Calling blocking code
# Blocks the event loop
asyncio.run_until_complete(do_blocking_io())
To avoid this, use
2. Forgetting to await coroutines
Any coroutines you launch need to be awaited, otherwise
async def main():
asyncio.create_task(some_coro())
asyncio.run_until_complete(main()) # Exits without awaiting some_coro
Always
Tips for Effective Usage
Here are some tips:
Practical Example
Here is an example fetching two web pages "correctly":
import asyncio
async def fetch(url):
print(f"Fetching {url}")
# Pretend we do I/O here
await asyncio.sleep(2)
return f"{url} result"
async def main():
print("Starting")
task1 = asyncio.create_task(fetch("url1"))
task2 = asyncio.create_task(fetch("url2"))
results = await asyncio.gather(task1, task2)
print(results)
print("Done")
if __name__ == "__main__":
asyncio.run(main())
This runs both fetches concurrently, waits for them to complete, and exits cleanly.
The key points are:
Hopefully this gives you a better understanding of how to effectively use