Core Features
httpx
-
Modern API Design: Inspired by the synchronous libraryrequests, the API is intuitive and easy to use.
-
HTTP/2 Support: Natively supports HTTP/2, which can enhance communication efficiency with compatible servers.
-
Sync and Async Compatibility: Supports both synchronous (httpx.Client) and asynchronous (httpx.AsyncClient) interfaces, suitable for mixed scenarios.
aiohttp
-
High Performance: Designed to be lightweight, optimized for high throughput scenarios, and generally faster than httpx.
-
Flexible Configuration: Provides fine-grained control over HTTP connections, headers, and sessions, suitable for complex requirements.
-
Mature Ecosystem: As an older library, it has an active community, rich documentation, and supports complex scenarios.
Basic Usage
httpx
import httpx
import asyncio
async def fetch_data():
async with httpx.AsyncClient() as client:
response = await client.get("https://api.example.com")
return response.json()
asyncio.run(fetch_data())
aiohttp
import aiohttp
import asyncio
async def fetch_data():
async with aiohttp.ClientSession() as session:
response = await session.get("https://api.example.com")
return await response.json()
asyncio.run(fetch_data())
High Concurrency Code Example:
import aiohttp
import asyncio
async def fetch_url(session, url):
"""Send a single POST request and return JSON result"""
async with session.post(url, json={"key": "value"}) as response:
return await response.json()
async def main():
"""High concurrency request example"""
url = "https://api.example.com/data" # Replace with your API address
async with aiohttp.ClientSession() as session: # Can be replaced with httpx for comparison
# Concurrently send 10 requests
tasks = [fetch_url(session, url) for _ in range(10)]
results = await asyncio.gather(*tasks)
# Output results
for result in results:
print(result)
if __name__ == "__main__":
asyncio.run(main())
JSON Requests
-
Both httpx and aiohttp support the “json=dict” syntax:
response = await client.post("https://api.example.com", json=payload) # Automatically sets Content-Type: application/json
⚠ Do not follow json= with a json.dumps string, or the server may return errors like [422 Unprocessable Entity].
-
Using data to manually serialize JSON:
import json
# httpx
async with httpx.AsyncClient() as client:
payload = json.dumps({"key": "value"})
response = await client.post("https://api.example.com", data=payload) # Automatically sets Content-Type: application/json
# aiohttp
async with aiohttp.ClientSession() as session:
payload = json.dumps({"key": "value"})
response = await session.post("https://api.example.com", data=payload, headers={"Content-Type": "application/json"}) # Must manually set headers
When using the data parameter and manually serialized JSON (like json.dumps), httpx will automatically add the Content-Type header, while aiohttp requires manual setting.
Resource Management
# Safe: Context manager automatically cleans up resources
async with httpx.AsyncClient() as client:
response = await client.post("https://api.example.com", json={"key": "value"})
# Safe: Context manager automatically cleans up resources
async with aiohttp.ClientSession() as session:
response = await session.post("https://api.example.com", json={"key": "value"})
# Unsafe: Manual session management may lead to leaks
session = aiohttp.ClientSession()
response = await session.post("https://api.example.com", json={"key": "value"})
await session.close() # Must explicitly close
Performance
-
aiohttp: Due to its lightweight design and highly optimized connection handling, it is usually 5-10% faster thanhttpx in high throughput scenarios (based on community benchmarks).
-
httpx: Due to its support for HTTP/2 and richer features, its performance is slightly lower thanaiohttp, but for small to medium projects, the difference is negligible.
Applicable Scenarios
-
Choose httpx:
-
When an intuitive API similar torequests is needed, suitable for rapid development.
-
When the project involves HTTP/2 or frequent JSON requests.
-
When a mixed scenario of synchronous and asynchronous is required.
-
Choose aiohttp:
-
When extreme performance is required, suitable for high throughput applications.
-
When developing both client-side and server-side asynchronous applications.
-
When fine-grained control over connections and headers is preferred.