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
| Concept | Description |
|---|---|
async def |
Defines a coroutine function |
await |
Pauses until the async operation completes |
asyncio.run() |
Entry point to run async code |
asyncio.gather() |
Run multiple coroutines concurrently |
aiohttp |
Async 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 Async | Use Sync |
|---|---|
| Multiple API calls | Single API call |
| I/O-bound tasks | CPU-bound tasks |
| Web scraping | Simple scripts |
| Real-time streaming | Sequential processing |
You've completed the Working with APIs module! Next, we'll learn about project structure. :::