浅度测评:requests、aiohttp、httpx 我应该用哪一个?

简介: 浅度测评:requests、aiohttp、httpx 我应该用哪一个?

摄影:产品经理与产品经理环游世界

在 Python 众多的 HTTP 客户端中,最有名的莫过于requestsaiohttphttpx。在不借助其他第三方库的情况下,requests只能发送同步请求;aiohttp只能发送异步请求;httpx既能发送同步请求,又能发送异步请求。

所谓的同步请求,是指在单进程单线程的代码中,发起一次请求后,在收到返回结果之前,不能发起下一次请求。所谓异步请求,是指在单进程单线程的代码中,发起一次请求后,在等待网站返回结果的时间里,可以继续发送更多请求。

今天我们来一个浅度测评,仅仅以多次发送 POST 请求这个角度来对比这三个库的性能。

测试使用的 HTTP 服务地址为http://122.51.39.219:8000/query,向它发送 POST 请求的格式如下图所示:

请求发送的 ts 字段日期距离今天大于10天,那么返回{"success": false},如果小于等于10天,那么返回{"success": true}

首先我们通过各个客户端使用相同的参数只发送一次请求,看看效果。

发送一次请求

requests

import requests
resp = requests.post('http://122.51.39.219:8000/query',
                     json={'ts': '2020-01-20 13:14:15'}).json()
print(resp)

运行效果如下图所示:

httpx

使用 httpx 发送同步请求:

import httpx
resp = httpx.post('http://122.51.39.219:8000/query',
                  json={'ts': '2020-01-20 13:14:15'}).json()
print(resp)

httpx 的同步模式与 requests 代码重合度99%,只需要把requests改成httpx即可正常运行。如下图所示:

使用 httpx 发送异步请求:

import httpx
import asyncio
asyncdef main():
    asyncwith httpx.AsyncClient() as client:
        resp = await client.post('http://122.51.39.219:8000/query',
                                 json={'ts': '2020-01-20 13:14:15'})
        result = resp.json()
        print(result)
asyncio.run(main())

运行效果如下图所示:

aiohttp

import aiohttp
import asyncio
asyncdef main():
    asyncwith aiohttp.ClientSession() as client:
        resp = await client.post('http://122.51.39.219:8000/query',
                                 json={'ts': '2020-01-20 13:14:15'})
        result = await resp.json()
        print(result)
asyncio.run(main())

运行效果如下图所示:

aiohttp 的代码与 httpx 异步模式的代码重合度90%,只不过把AsyncClient换成了ClientSession,另外,在使用 httpx 时,当你await client.post时就已经发送了请求。但是当使用aiohttp时,只有在awiat resp.json() 时才会真正发送请求。

发送100次请求

我们现在随机生成一个距离今天在5-15天的日期,发送到 HTTP接口中。如果日期距离今天超过10天,那么返回的数据的 False,如果小于等于10天,那么返回的数据是 True。

我们发送100次请求,计算总共耗时。

requests

在前几天的文章中,我们提到,使用requests.post每次都会创建新的连接,速度较慢。而如果首先初始化一个 Session,那么 requests 会保持连接,从而大大提高请求速度。所以在这次测评中,我们分别对两种情况进行测试。

不保持连接

import random
import time
import datetime
import requests
def make_request(body):
    resp = requests.post('http://122.51.39.219:8000/query', json=body)
    result = resp.json()
    print(result)
def main():
    start = time.time()
    for _ in range(100):
        now = datetime.datetime.now()
        delta = random.randint(5, 15)
        ts = (now - datetime.timedelta(days=delta)).strftime('%Y-%m-%d %H:%M:%S')
        make_request({'ts': ts})
    end = time.time()
    print(f'发送100次请求,耗时:{end - start}')
if __name__ == '__main__':
    main()

运行效果如下图所示:


发送100次请求,requests 不保持连接时耗时2.7秒

保持连接

对代码稍作修改,使用同一个 Session 发送请求:

import random
import time
import datetime
import requests
def make_request(session, body):
    resp = session.post('http://122.51.39.219:8000/query', json=body)
    result = resp.json()
    print(result)
def main():
    session = requests.Session()
    start = time.time()
    for _ in range(100):
        now = datetime.datetime.now()
        delta = random.randint(5, 15)
        ts = (now - datetime.timedelta(days=delta)).strftime('%Y-%m-%d %H:%M:%S')
        make_request(session, {'ts': ts})
    end = time.time()
    print(f'发送100次请求,耗时:{end - start}')
if __name__ == '__main__':
    main()

运行效果如下图所示:

发送100次请求,requests 保持连接耗时1.4秒

httpx

同步模式

代码如下:

import random
import time
import datetime
import httpx
def make_request(client, body):
    resp = client.post('http://122.51.39.219:8000/query', json=body)
    result = resp.json()
    print(result)
def main():
    session = httpx.Client()
    start = time.time()
    for _ in range(100):
        now = datetime.datetime.now()
        delta = random.randint(5, 15)
        ts = (now - datetime.timedelta(days=delta)).strftime('%Y-%m-%d %H:%M:%S')
        make_request(session, {'ts': ts})
    end = time.time()
    print(f'发送100次请求,耗时:{end - start}')
if __name__ == '__main__':
    main()

运行效果如下图所示:

发送100次请求,httpx 同步模式耗时1.5秒左右。

异步模式

代码如下:

import httpx
import random
import datetime
import asyncio
import time
asyncdef request(client, body):
    resp = await client.post('http://122.51.39.219:8000/query', json=body)
    result = resp.json()
    print(result)
asyncdef main():
    asyncwith httpx.AsyncClient() as client:
        start = time.time()
        task_list = []
        for _ in range(100):
            now = datetime.datetime.now()
            delta = random.randint(5, 15)
            ts = (now - datetime.timedelta(days=delta)).strftime('%Y-%m-%d %H:%M:%S')
            req = request(client, {'ts': ts})
            task = asyncio.create_task(req)
            task_list.append(task)
        await asyncio.gather(*task_list)
        end = time.time()
    print(f'发送100次请求,耗时:{end - start}')
asyncio.run(main())

运行效果如下图所示:

发送100次请求,httpx 异步模式耗时0.6秒左右。

aiohttp

测试代码如下:

import aiohttp
import random
import datetime
import asyncio
import time
asyncdef request(client, body):
    resp = await client.post('http://122.51.39.219:8000/query', json=body)
    result = await resp.json()
    print(result)
asyncdef main():
    asyncwith aiohttp.ClientSession() as client:
        start = time.time()
        task_list = []
        for _ in range(100):
            now = datetime.datetime.now()
            delta = random.randint(5, 15)
            ts = (now - datetime.timedelta(days=delta)).strftime('%Y-%m-%d %H:%M:%S')
            req = request(client, {'ts': ts})
            task = asyncio.create_task(req)
            task_list.append(task)
        await asyncio.gather(*task_list)
        end = time.time()
    print(f'发送100次请求,耗时:{end - start}')
asyncio.run(main())

运行效果如下图所示:

发送100次请求,使用 aiohttp 耗时0.3秒左右

发送1000次请求

由于 request 保持连接的速度比不保持连接快,所以我们这里只用保持连接的方式来测试。并且不打印返回的结果。

requests

运行效果如下图所示:

发送1000次请求,requests 耗时16秒左右

httpx

同步模式

运行效果如下图所示:

发送1000次请求,httpx 同步模式耗时18秒左右

异步模式

运行效果如下图所示:

发送1000次请求,httpx 异步模式耗时5秒左右

aiohttp

运行效果如下图所示:

发送1000次请求,aiohttp 耗时4秒左右

总结

如果你只发几条请求。那么使用 requests 或者 httpx 的同步模式,代码最简单。

如果你要发送很多请求,但是有些地方要发送同步请求,有些地方要发送异步请求,那么使用 httpx 最省事。

如果你要发送很多请求,并且越快越好,那么使用 aiohttp 最快。

这篇测评文章只是一个非常浅度的评测,只考虑了请求速度这一个角度。如果你要在生产环境使用,那么你可以做更多实验来看是不是符合你的实际使用情况。

目录
相关文章
|
29天前
|
缓存 自然语言处理 数据可视化
知识图谱与RAG融合实战:用LightRAG极速构建智能问答系统
本文介绍了LightRAG——一种融合知识图谱与RAG技术的轻量级框架,通过三重检索机制(向量、关键词与图检索)提升问答系统的准确性与全面性,并提供快速构建、可视化、性能优化及多领域应用方案。
|
机器学习/深度学习 编解码 自然语言处理
YOLOv8改进 | 主干篇 | RevColV1可逆列网络(特征解耦助力小目标检测)
YOLOv8改进 | 主干篇 | RevColV1可逆列网络(特征解耦助力小目标检测)
486 0
YOLOv8改进 | 主干篇 | RevColV1可逆列网络(特征解耦助力小目标检测)
|
监控 安全 网络安全
SSH服务端配置、优化加速、安全防护
CentOS7自带的SSH服务是OpenSSH中的一个独立守护进程SSHD。由于使用telnet在网络中是明文传输所以用其管理服务器是非常不安全的不安全,SSH协议族可以用来对服务器的管理以及在计算机之间传送文件。
3012 0
|
测试技术 API Python
Python中requests、aiohttp、httpx性能对比
这篇文章对比了Python中三个流行的HTTP客户端库:requests、aiohttp和httpx,在发送HTTP请求时的性能,并提供了测试代码和结果,以帮助选择适合不同应用场景的库。
1005 2
|
3月前
|
算法 IDE 开发工具
蓝桥杯备赛经验帖
本文是作者blue分享的蓝桥杯备赛经验帖,旨在帮助刚接触算法竞赛的新手。文章从个人参赛经历出发,详细介绍了蓝桥杯的OI赛制特点、比赛流程以及备赛建议。作者强调了重点掌握基础数论、DFS、数组操作、二分法、动态规划等知识,并建议多参与线上赛,熟悉输入输出规则,同时避免盲目刷题或过度依赖力扣。通过参赛,作者不仅提升了编码能力,还结识了优秀的朋友,认识到自身差距,激励自己不断进步。此经验适合新手参考,大佬可略过。
292 4
|
10月前
|
安全 程序员 测试技术
推荐7款程序员常用的API管理工具
本文所有工具都已收录至Awesome Tools,程序员常用高效实用工具、软件资源精选,办公效率提升利器。
691 3
|
11月前
|
网络协议 网络安全
ssl证书下载
【10月更文挑战第4天】ssl证书下载
446 3
|
测试技术 API Python
Python3 新一代Http请求库Httpx使用(详情版)(下)
Python3 新一代Http请求库Httpx使用(详情版)
1527 0
|
测试技术 Apache
使用 Apache JMeter Flexible File Writer 插件的详细指南
Apache JMeter 是开源性能测试工具,用于负载测试。Flexible File Writer 是一个插件,用于自定义格式记录测试结果。安装该插件需通过 JMeter 的 Plugins Manager。配置时,添加监听器到测试计划,设置输出文件、文件格式及字段。执行测试后,结果将按指定格式写入 CSV 文件。此插件增强了数据记录的灵活性,便于分析和报告。