
上周帮人 code review,代码里同时 import 了三个 HTTP 库。
问他为什么,他说:“我看别人项目里都有,就全加上了。”
有点无语,但很理解——这三个库确实容易让人迷糊。requests 用了好多年,httpx 冒出来说自己是“现代版 requests”,aiohttp 又跳出来说“我更快”,结果就是很多人稀里糊涂全装上了。
今天把这三个库掰开了说清楚,讲讲我自己的选法。
不想看长文的,直接看这四个判断:
如果你现在用 requests 跑得好好的,没有性能问题——别动。继续往下看只是想了解一下。
requests 的地位不用多说。2011 年发布,Star 数 50k+,几乎每个 Python 程序员入门第一个学的 HTTP 库。
设计哲学很简单:让 HTTP 请求读起来像人话。
importrequests
response = requests.get(
"https://api.github.com/user",
params={"page": 1, "per_page": 10},
headers={"Authorization": "token YOUR_TOKEN"},
timeout=5
)
print(response.status_code)
print(response.json())requests.get() 就是“去拿”,params 就是参数,timeout 就是超时。不需要知道什么 coroutine、event loop,对新手极度友好。
说实话,就一个:同步的。
发一个请求,线程就卡在那等服务器响应。并发请求 1000 个接口,它一个一个来,要跑很久。
之前写一个数据采集脚本,用 requests 跑了 40 分钟。换了个方案,10 分钟搞定。差点把头发薅秃。
httpx 是 2020 年出的,作者之一是 Encode 团队(FastAPI 背后那帮人)。它的目标很明确:做一个同时支持同步和异步的 requests。
importhttpx
# 同步 —— 和 requests 几乎一样
response = httpx.get("https://api.github.com/user")
print(response.json())
# 异步 —— 同样简洁
asyncwithhttpx.AsyncClient() asclient:
response = awaitclient.get("https://api.github.com/user")
print(response.json())API 和 requests 几乎一样,只是多了个 await。熟悉 requests 的人上手成本几乎为零。
并发请求变得极简单:
importhttpx
importasyncio
asyncdeffetch_all(urls):
asyncwithhttpx.AsyncClient() asclient:
tasks = [client.get(url) forurlinurls]
responses = awaitasyncio.gather(*tasks)
return [r.json() forrinresponses]
# 1000个URL?5秒跑完
urls = [f"https://api.example.com/item/{i}"foriinrange(1000)]
results = asyncio.run(fetch_all(urls))性能跟 aiohttp 一个水平,但语法跟 requests 一样干净。
aiohttp 是 asyncio 生态里最早的 HTTP 客户端,2014 年就存在了。它的特点很明确:纯异步,性能拉满。
API 写法跟 requests 不太一样,有一点“异步味”:
importaiohttp
importasyncio
asyncdeffetch(url):
asyncwithaiohttp.ClientSession() assession:
asyncwithsession.get(url) asresponse:
returnawaitresponse.json()
asyncdefmain():
tasks = [fetch(f"https://api.example.com/item/{i}") foriinrange(1000)]
results = awaitasyncio.gather(*tasks)
asyncio.run(main())代码量和 httpx 异步模式差不多,但 aiohttp 更“原生 asyncio”一点。
两个明确的用途:
asyncio.run()。总结了一套决策流程:
你的项目需要异步吗?
│
├─ 不需要 → 用 requests,跑得好就别动
│
└─ 需要 → 新项目?→ httpx(同步异步都能跑)
已有 asyncio 项目?→ aiohttp我自己的偏好:
坑1:不要在 asyncio 项目里混用 requests
# 错误:卡住事件循环
asyncdefget_data():
data = requests.get(url) # 这会阻塞整个事件循环
returndata.json()在 asyncio 项目里调用同步代码,高并发优势全没了。换 httpx 或 aiohttp。
坑2:httpx 默认不验证 SSL
# 危险!直接跳过证书验证
client = httpx.AsyncClient(verify=False)生产环境一定要配置证书验证。有内部 HTTPS 的,用 verify="/path/to/ca-bundle.crt" 指定路径。
坑3:aiohttp 不要每次请求都 new Session
# 错误:重复创建 Session,有连接开销
asyncdefbad_fetch(url):
asyncwithaiohttp.ClientSession() assession: # 每次都新建
asyncwithsession.get(url) asresp:
returnawaitresp.json()
# 正确:全局复用 Session
asyncwithaiohttp.ClientSession() assession:
tasks = [fetch(session, url) forurlinurls]
awaitasyncio.gather(*tasks)高频请求下,Session 重复创建影响明显。
requests 是老将,稳定、皮实;httpx 是新星,一手抓简洁一手抓性能,接班 requests 的势头很明显;aiohttp 在 asyncio 生态里没有对手。
建议:不要三个都装,根据场景选一个用到底就好。
“无他,惟手熟尔”!有需要的用起来!
本文分享自 Nicholas与Pypi 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!