Lesson 16 of 20

Working with APIs

Async with asyncio

4 min read

Async programming lets you run multiple API calls concurrently. Instead of waiting for each call to complete, you can start several at once.

Why Async?

Synchronous (slow):
Call 1: |-------|
Call 2:         |-------|
Call 3:                 |-------|
Total: ~3 seconds

Asynchronous (fast):
Call 1: |-------|
Call 2: |-------|
Call 3: |-------|
Total: ~1 second

Basic Async Syntax

import asyncio

# Define an async function with 'async def'
async def fetch_data():
    print("Starting...")
    await asyncio.sleep(1)  # Non-blocking wait
    print("Done!")
    return "data"

# Run async function
result = asyncio.run(fetch_data())

Async HTTP with aiohttp

pip install aiohttp
import aiohttp
import asyncio

async def fetch_url(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            return await response.json()

# Run it
data = asyncio.run(fetch_url("https://api.example.com/data"))

Making Concurrent API Calls

import aiohttp
import asyncio
import os

async def chat_completion(session, prompt):
    """Make a single chat completion request."""
    url = "https://api.openai.com/v1/chat/completions"
    headers = {
        "Authorization": f"Bearer {os.getenv('OPENAI_API_KEY')}",
        "Content-Type": "application/json"
    }
    data = {
        "model": "gpt-4",
        "messages": [{"role": "user", "content": prompt}]
    }

    async with session.post(url, headers=headers, json=data) as response:
        result = await response.json()
        return result["choices"][0]["message"]["content"]

async def batch_completions(prompts):
    """Process multiple prompts concurrently."""
    async with aiohttp.ClientSession() as session:
        tasks = [chat_completion(session, p) for p in prompts]
        results = await asyncio.gather(*tasks)
        return results

# Process 5 prompts concurrently
prompts = [
    "What is Python?",
    "What is JavaScript?",
    "What is Rust?",
    "What is Go?",
    "What is Ruby?"
]

results = asyncio.run(batch_completions(prompts))
for prompt, result in zip(prompts, results):
    print(f"Q: {prompt}\nA: {result[:100]}...\n")

Key Concepts

ConceptDescription
async defDefines a coroutine function
awaitPauses until the async operation completes
asyncio.run()Entry point to run async code
asyncio.gather()Run multiple coroutines concurrently
aiohttpAsync HTTP client library

Error Handling in Async

async def safe_fetch(session, url):
    try:
        async with session.get(url, timeout=10) as response:
            response.raise_for_status()
            return await response.json()
    except asyncio.TimeoutError:
        print(f"Timeout: {url}")
        return None
    except aiohttp.ClientError as e:
        print(f"Error: {e}")
        return None

async def fetch_all(urls):
    async with aiohttp.ClientSession() as session:
        tasks = [safe_fetch(session, url) for url in urls]
        return await asyncio.gather(*tasks)

When to Use Async

Use AsyncUse Sync
Multiple API callsSingle API call
I/O-bound tasksCPU-bound tasks
Web scrapingSimple scripts
Real-time streamingSequential processing

You've completed the Working with APIs module! Next, we'll learn about project structure. :::

Quick check: how does this lesson land for you?

Quiz

Module 4: Working with APIs

Take Quiz
FREE WEEKLY NEWSLETTER

Stay on the Nerd Track

One email per week — courses, deep dives, tools, and AI experiments.

No spam. Unsubscribe anytime.