Python中異步HTTP客戶端/服務器框架aiohttp的使用全面指南
什么是 aiohttp
aiohttp 是一個基于 Python asyncio 的異步 HTTP 客戶端/服務器框架,專為高性能網(wǎng)絡(luò)編程設(shè)計。它提供了:
- 異步 HTTP 客戶端(類似異步版 requests)
- 異步 HTTP 服務器(類似異步版 Flask/Django)
- 完整的 WebSocket 支持
- 高效的連接池管理
核心優(yōu)勢
| 特性 | 描述 |
|---|---|
| 異步非阻塞 | 單線程處理數(shù)千并發(fā)連接 |
| 高性能 | 遠超同步框架(如 requests)的吞吐量 |
| 輕量級 | 簡潔的API,無復雜依賴 |
| 全面協(xié)議支持 | HTTP/1.1, HTTP/2(客戶端), WebSocket |
| 生態(tài)完善 | 良好文檔和活躍社區(qū) |
基礎(chǔ)用法 - HTTP客戶端
安裝
pip install aiohttp
基本GET請求
import aiohttp
import asyncio
async def main():
async with aiohttp.ClientSession() as session:
async with session.get('https://api.example.com/data') as response:
print("狀態(tài)碼:", response.status)
print("響應內(nèi)容:", await response.text())
asyncio.run(main())
POST請求示例
async def post_example():
async with aiohttp.ClientSession() as session:
# 表單數(shù)據(jù)
async with session.post(
'https://httpbin.org/post',
data={'key': 'value'}
) as response:
print(await response.json())
# JSON數(shù)據(jù)
async with session.post(
'https://api.example.com/users',
json={'name': 'Alice', 'age': 30}
) as response:
print(await response.json())
高級用法
并發(fā)請求
async def fetch(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.text()
async def concurrent_requests():
urls = [
'https://api.example.com/item/1',
'https://api.example.com/item/2',
'https://api.example.com/item/3'
]
tasks = [fetch(url) for url in urls]
results = await asyncio.gather(*tasks)
for url, content in zip(urls, results):
print(f"{url}: {content[:50]}...")
asyncio.run(concurrent_requests())
超時控制
async def timeout_example():
timeout = aiohttp.ClientTimeout(total=5) # 5秒總超時
async with aiohttp.ClientSession(timeout=timeout) as session:
try:
async with session.get('https://slow-api.example.com') as response:
return await response.text()
except asyncio.TimeoutError:
print("請求超時!")
流式處理大響應
async def stream_response():
async with aiohttp.ClientSession() as session:
async with session.get('https://large-file.example.com') as response:
with open('large_file.txt', 'wb') as f:
async for chunk in response.content.iter_chunked(1024):
f.write(chunk)
print(f"已接收 {len(chunk)} 字節(jié)")
服務器端開發(fā)
基本HTTP服務器
from aiohttp import web
async def handle(request):
name = request.match_info.get('name', "World")
return web.Response(text=f"Hello, {name}!")
app = web.Application()
app.add_routes([
web.get('/', handle),
web.get('/{name}', handle)
])
if __name__ == '__main__':
web.run_app(app, port=8080)
REST API示例
async def get_users(request):
users = [{'id': 1, 'name': 'Alice'}, {'id': 2, 'name': 'Bob'}]
return web.json_response(users)
async def create_user(request):
data = await request.json()
# 實際應用中這里會保存到數(shù)據(jù)庫
return web.json_response({'id': 3, **data}, status=201)
app = web.Application()
app.add_routes([
web.get('/api/users', get_users),
web.post('/api/users', create_user)
])
WebSocket服務器
async def websocket_handler(request):
ws = web.WebSocketResponse()
await ws.prepare(request)
async for msg in ws:
if msg.type == aiohttp.WSMsgType.TEXT:
if msg.data == 'close':
await ws.close()
else:
await ws.send_str(f"ECHO: {msg.data}")
elif msg.type == aiohttp.WSMsgType.ERROR:
print('WebSocket連接異常關(guān)閉')
return ws
???????app.add_routes([web.get('/ws', websocket_handler)])進階擴展
中間件示例
async def auth_middleware(app, handler):
async def middleware(request):
# 驗證API密鑰
if request.headers.get('X-API-Key') != 'SECRET_KEY':
return web.json_response({'error': 'Unauthorized'}, status=401)
return await handler(request)
return middleware
app = web.Application(middlewares=[auth_middleware])
HTTP/2客戶端支持
async def http2_request():
conn = aiohttp.TCPConnector(force_close=True, enable_cleanup_closed=True)
async with aiohttp.ClientSession(connector=conn) as session:
async with session.get(
'https://http2.akamai.com/',
headers={'accept': 'text/html'}
) as response:
print("HTTP版本:", response.version)
print("內(nèi)容:", await response.text()[:200])
性能優(yōu)化配置
# 自定義連接器配置
connector = aiohttp.TCPConnector(
limit=100, # 最大并發(fā)連接數(shù)
limit_per_host=20, # 單主機最大連接數(shù)
ssl=False, # 禁用SSL驗證(僅用于測試)
force_close=True # 避免連接延遲關(guān)閉
)
# 自定義會話配置
session = aiohttp.ClientSession(
connector=connector,
timeout=aiohttp.ClientTimeout(total=30),
headers={'User-Agent': 'MyApp/1.0'},
cookie_jar=aiohttp.CookieJar(unsafe=True)
)
最佳實踐
重用ClientSession:避免為每個請求創(chuàng)建新會話
使用連接池:合理配置TCPConnector參數(shù)
超時設(shè)置:總是配置合理的超時時間
資源清理:使用async with確保資源釋放
錯誤處理:捕獲并處理常見網(wǎng)絡(luò)異常
try:
async with session.get(url) as response:
response.raise_for_status()
return await response.json()
except aiohttp.ClientError as e:
print(f"請求錯誤: {e}")
完整示例
import aiohttp
import asyncio
from aiohttp import web
# 客戶端示例
async def fetch_data():
async with aiohttp.ClientSession() as session:
# 并發(fā)請求多個API
urls = [
'https://jsonplaceholder.typicode.com/posts/1',
'https://jsonplaceholder.typicode.com/comments/1',
'https://jsonplaceholder.typicode.com/albums/1'
]
tasks = []
for url in urls:
tasks.append(session.get(url))
responses = await asyncio.gather(*tasks)
results = []
for response in responses:
results.append(await response.json())
return results
# 服務器示例
async def handle_index(request):
return web.Response(text="Welcome to aiohttp server!")
async def handle_api(request):
data = await fetch_data()
return web.json_response(data)
# 創(chuàng)建應用
app = web.Application()
app.add_routes([
web.get('/', handle_index),
web.get('/api', handle_api)
])
# 啟動服務器
async def start_server():
runner = web.AppRunner(app)
await runner.setup()
site = web.TCPSite(runner, 'localhost', 8080)
await site.start()
print("Server running at http://localhost:8080")
# 保持運行
while True:
await asyncio.sleep(3600) # 每小時喚醒一次
if __name__ == '__main__':
asyncio.run(start_server())
總結(jié)
aiohttp 是 Python 異步生態(tài)中處理 HTTP 通信的首選工具,它提供了:
- 高效客戶端:用于高性能爬蟲、API調(diào)用
- 輕量級服務器:構(gòu)建高性能Web服務和API
- WebSocket支持:實現(xiàn)實時雙向通信
- 連接池管理:優(yōu)化資源利用率
通過合理利用 aiohttp 的異步特性,開發(fā)者可以輕松構(gòu)建出能夠處理數(shù)萬并發(fā)連接的高性能網(wǎng)絡(luò)應用,同時保持代碼的簡潔性和可維護性。
到此這篇關(guān)于Python中異步HTTP客戶端/服務器框架aiohttp的使用全面指南的文章就介紹到這了,更多相關(guān)Python異步框架aiohttp內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
PyQt5中QPushButton的用法詳細解析與應用實戰(zhàn)
PyQt5 是一個用于創(chuàng)建圖形用戶界面的 Python 綁定庫,它基于 Qt5 應用程序框架,在 PyQt5 中,QPushButton 是一個常用的控件,用于創(chuàng)建按鈕,允許用戶通過點擊來觸發(fā)某些操作,本文將詳細介紹 QPushButton 的用法,并通過實際案例來展示其強大的功能2024-07-07
詳解python函數(shù)傳參傳遞dict/list/set等類型的問題
這篇文章主要介紹了詳解python函數(shù)傳參傳遞dict/list/set等類型的問題,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-04-04
python?numpy?中l(wèi)inspace函數(shù)示例詳解
這篇文章主要介紹了python?numpy?中l(wèi)inspace函數(shù),本文我們通過示例學習了linspace函數(shù),如果你熟悉NumPy,一定也注意到還有np.arange函數(shù),兩者最大差異是,linspace能夠精確控制終止值終值,而arange能夠更直接地控制序列中值之間的增量,需要的朋友可以參考下2023-03-03
Keras實現(xiàn)DenseNet結(jié)構(gòu)操作
這篇文章主要介紹了Keras實現(xiàn)DenseNet結(jié)構(gòu)操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07
Python數(shù)據(jù)結(jié)構(gòu)之列表與元組詳解
序列是Python中最基本的數(shù)據(jù)結(jié)構(gòu)。序列中的每個元素都分配一個數(shù)字 - 它的位置,或索引,第一個索引是0,第二個索引是1,依此類推,元組與列表類似,不同之處在于元組的元素不能修改。元組使用小括號,列表使用方括號2021-10-10

