Technology / Programming

How to Create an Async API Call with asyncio

How to Create an Async API Call with asyncio picture: A
Follow us
Updated on June 5, 2024

Compared to other programming languages, Python can be much slower at making API calls.

That's because, by design, Python is a blocking language. This means Python code will not be executed until the previous set of instructions has finished. This holds true for definition calls, too.

On the other hand, programming languages like JavaScript are non-blocking languages. That means if a chunk of code is waiting for something to happen, that chunk can release control back to the JavaScript interpreter to do other things. 

This considerably improves JavaScript's efficiency because the computer processing JavaScript code isn't idle. Instead, that computer can use its processor cycles for other chunks of code.

Wouldn't it be nice if Python could use async functions, too?

It turns out that Python can use asynchronous code. Though creating callbacks in Python is a little bit more difficult than in JavaScript, a library called asyncio makes writing asynchronous Python code easy. Let's discuss how.

An Overview of How to Create an Async API Call with asyncio [Video]

In the below video, Ben Finkel covers how to create an asynchronous API call in Python. There are plenty of detailed articles that discuss the ins and outs of synchronous and asynchronous programming, but Ben believes it's more helpful to see it in action and learn how it can improve the responsiveness of your software.

An Intro to asyncio 

By design, Python is a blocking language. That means it must finish processing lines of code before it can move on to other tasks. Thankfully, with a library called asyncio, Python can use the same async / await syntax that JavaScript uses to create concurrent code.

Before we go any further, we need to clarify a few things: 

First, asyncio has many different uses. This article is not meant as a full tutorial on how to use all its functions. Instead, it is only meant to demonstrate how to use asyncio in Python to write concurrent, non-blocking code. If you want to see all the functions that asyncio can use, it's strongly recommended that you read this library's documentation at Python.org.

Second, we provide two Python code examples below. One example demonstrates how Python uses async /await calls with asyncio. We will reference this set of example syntax throughout the rest of this article. The other example code demonstrates how a traditional Get request is made in Python using the Requests Python library. Again, we will not reference this set of code. It is only included as an example to compare against what asynchronous code looks like in Python.

Third, since we will reference the asynchronous code throughout this article, we will include reference comments in the code example below. For instance, we may refer to 'Reference 1 in the code example.' Therefore, we will notate Reference 1 with a comment in the example code ( # Reference 1).

Fourth, examine the asynchronous Python code example closely. You'll notice the first function is called 'count()' and is located at Reference 1 in the code example. We won't discuss this function at all other than to say its goal is to count once a second and then display that count in the console. This function serves as a visual example of how asynchronous Python code works. 

Feel free to copy and run that asynchronous Python code example below. What do you think will happen? When will the response to 'get_delay()' be displayed in the console?

How to Make Async Get Requests in Python

Before you can make async and await calls in Python, you need to install the asyncio library in your Python environment. This can be done with Python's Pip package manager.

How to Install asyncio in Python

To access Python's pip package manager, you can run it from your system's command-line interface. Pip is included by default if you have Python version 3.4 or later. Use this command: 

pip install asyncio

That will enable asyncio to be available in your Python projects going forward.

Next, import the asyncio library into your Python code (Reference 2 in the example below).

import asyncio

Finally, for the purposes of this article, we are going to use the ClientSession function from the Aiohttp class code (Reference 3 in the example below).

from aiohttp import ClientSession

Aiohttp is an asynchronous HTTP client and server package for Python using asyncio. If you are familiar with Express for NodeJS, you will feel very comfortable with Aiohttp. Because Aiohttp is a separate package from asyncio, it must also be installed through the Pip package manager. Use the same Pip install command above but replace 'asyncio' with 'aiohttp.'

Make Async Get requests in Python with Aiohttp

Before using Aiohttp to perform Get requests in Python, make sure to have the asyncio library installed and imported into your Python project first. Aiohttp depends on asyncio due to the asynchronous nature of HTTP Get requests.

Using Aiohttp to make Get requests depends on the async and await features of the asyncio library. This is very similar to JavaScript. Because asynchronous operations in Python are not built-in and depend on the asyncio library, we need to first call a function of the asyncio library to kick off the asynchronous code operations (Reference 4 in the example below).

asyncio.run(main())

asyncio leverages the blocking nature of Python to function. Basically, this function call is calling another function. This second function (Reference 5 in the example below) is what we then use to call the rest of our asynchronous functions.

async def main(): 
      await asynchio.gather(get_delay(5),count())

The 'main()' function uses another asyncio function to call both the 'get_delay()' and 'count()' functions.

It might seem like a lot of work to call a couple of functions asynchronously, but this is required due to how Python is designed. Because Python is blocking by nature, we need to call a single function to start the asynchronous code process.

Any functions that are not async / await functions will not be processed until after the 'asyncio.run(main())' call is made. So, for instance, if you had another function after 'asyncio.run(main())' that adds two numbers together (Reference 6 in the example below), that function won't run until after all of the other async /await functions finish from 'asyncio.run(main())'.

Another Way to Visualize How Async Code Runs in Python:

  1. asyncio.run calls the 'main()' function.

  2. 'main()' calls both 'get_delay()' and 'count()'

  3. Both 'get_delay()' and 'count()' process their code at the same time but independent of each other

  4. Both 'get_delay()' and 'count()' finishes processing and returns priority back to 'main().'

  5. 'main()' is now finished, so it returns priority back to asyncio.run.

  6. asyncio.run is now finished, so the rest of the code runs (otherwise, the 'addTwoNumbers()' finally executes).

Let's ignore the 'count()' function and focus on the 'get_delay()' function. The 'get_delay()' function is not complicated. Let's walk through it.

First, this function defines the endpoint for the API it wants to call. Then it prints some text to the console. That text isn't important. It's only meant as a visual queue that the 'get_delay()' function is working.

Next, we make an async call using the 'ClientSession()' method from that Aiohttp library. We design the object from 'ClientSession()' simply as 'session.'

Inside that asynchronous call, we set the variable’s value called 'response' to the actual response of the HTTP Get request that was made by 'session.read()'. The 'session.read()' function knows what HTTP API URL and endpoint to use when we define 'session' using 'ClientSession().'

Once the 'session.read()' receives a message back from 'http://httpbin.org/delay/5', it assigns that message to 'response.' Then 'response' is printed to the console.

All of this is happening while 'count()' is processing and outputting its count to the console as well.

from aiohttp import ClientSession
 base_url = 'http://httpbin.org'
 async def count()
  for I in [1,2,3,4,5]:
  print(i)
  await asyncio.sleep(1)
 async def get_delay(seconds)
  endpoint = f'/delay/{seconds}'
  print(f'Getting with {seconds} delay … ')
  async with ClienSession(base_url+endpoint) as session:
   response = await response.read()
   print(response)
 async def main():
  await asynchio.gather(get_delay(5),count())
 asyncio.run(main())
 def addTwoNumbers (x, y):
  print(x + y)
 addTwoNumbers (2, 5)
 print('Okay! All finished getting.')
base_url = 'http://httpbin.org/'
def get_delay(seconds):
 endpoint = f'/delay/{seconds}'
 print(f'Getting with {seconds} delay … ')
 resp = requests.get(base_url+endpoint)
 data = resp.json()
 print(data)
get_delay(5)
print('Okay! All finished getting.')

Wrapping Up

We covered a lot of information in this article, but we barely scratched the surface of async operations in Python or Python development in general. If you want to learn more about Python, consider taking an Automation with Python course.

Let's recap what we talked about. Python is a blocking programming language by design. Unfortunately, it doesn't understand the concept of asynchronous code. However, we can write asynchronous code with Python using a library called asyncio.

Python has another library called aiohttp, an HTTP client and server based on asyncio. Thus, we can use asyncio to create asynchronous API calls.

This is useful for optimizing code. Because Python is a blocking language, it is possible to cause idle time waiting for Python to finish tasks (like waiting for API calls). Using asynchronous code, we can keep Python constantly working without idle time.

Want to learn more about Python? Check out our Introduction to Python for Network Engineers course with John McGovern. 


Download

By submitting this form you agree to receive marketing emails from CBT Nuggets and that you have read, understood and are able to consent to our privacy policy.


Don't miss out!Get great content
delivered to your inbox.

By submitting this form you agree to receive marketing emails from CBT Nuggets and that you have read, understood and are able to consent to our privacy policy.

Recommended Articles

Get CBT Nuggets IT training news and resources

I have read and understood the privacy policy and am able to consent to it.

© 2024 CBT Nuggets. All rights reserved.Terms | Privacy Policy | Accessibility | Sitemap | 2850 Crescent Avenue, Eugene, OR 97408 | 541-284-5522