Python’s asyncio
library is the built-in Python library for running code concurrently with the async
/await
keywords. The asyncio
library is ideal for IO bound and structured network code. The difference between when to use the run
command and the run_until_complete
command with a loop
is subtle but could have real implications for your code. In this post we’ll go over:
- What is AsyncIO Run?
- asyncio.run example
- What is AsyncIO’s Run Until Complete?
- asyncio.loop.run_until_complete example
- A Commentary on AsyncIO loops
- When to Use AsyncIO Run vs AsyncIO Loop’s Run Until Complete
AsyncIO Run – asyncio.run()
asyncio.run()
is a high-level API in the asyncio
library. It takes one required parameter, a coroutine, and one default named parameter, debug
, which is set to False. The coroutine passed into asyncio.run()
must be an async
/await
function. As I said earlier, this is a high-level API in the asyncio
library, and under the hood it actually calls loop.run_until_complete()
.
This is the recommended entry point for asynchronous programs and should only be called once. The run
function creates, executes, and closes a loop
to run the run_until_complete
function.
asyncio.run() example
We’ll use a simple example of waiting for 1 second using the asyncio.sleep()
function. We’ll create an async
test function that takes no parameters. All it does is print out the current time, await
a sleep of 1, and then print out the current time again. Then we’ll use the async.run()
function to test it.
import asyncio
import time
async def test():
print(time.time())
await asyncio.sleep(1)
print(time.time())
asyncio.run(test())
It should print out something like this:
AsyncIO Run Until Complete – asyncio.loop.run_until_complete()
asyncio.loop.run_until_complete()
is a low-level API in the asyncio
native Python library. The function takes one parameter, a future
object. A coroutine or task defined by the async
/await
keywords is a future
object. That’s why we can call asyncio.loop.run_until_complete()
with asyncio.run()
.
In order to use the asyncio.loop
object’s run_until_complete()
function, we need to actually have an asynio.loop
object already instantiated or instantiate one on the call.
asyncio.loop.run_until_complete() example
We will use the exact same function we used above in our example of asyncio.run()
. We’ll create a function that prints the time, sleeps for a second, and then prints the time again. The only difference is how we’re going to run it.
In this example, we’re going to use asyncio.new_event_loop()
to create an async.loop
object and then call run_until_complete()
on the test()
function. We should get the exact same result.
import asyncio
import time
async def test():
print(time.time())
await asyncio.sleep(1)
print(time.time())
asyncio.new_event_loop().run_until_complete(test())
It should print out something like this:
Comment on AsyncIO Loops
Event loops are the core of asynchronous functions in Python. They run tasks, callbacks, network I/O, and subprocesses. Event loops are not meant to be used directly. They can be, but they shouldn’t be. They interact with asyncio
’s low-level APIs.
When to use asyncio.run vs asyncio.loop.run_until_complete
You should almost always use asyncio.run()
. The only time you should use the run_until_complete()
function over run()
is if you need access to other low-level APIs. Modern applications are suggested to use asyncio.run()
.
Further Reading
- Matrix Multiplication in Python with Lists
- Build a Neural Network from Scratch in Python 3
- Build Your Own Text Summarizer in Python
- Web Scraping with Python, Selenium, and Beautiful Soup 4
- How to Send a Web API Request in Python
I run this site to help you and others like you find cool projects and practice software skills. If this is helpful for you and you enjoy your ad free site, please help fund this site by donating below! If you can’t donate right now, please think of us next time.

2 thoughts on “Python AsyncIO Run vs Run Until Complete”