现在的人对于通过http协议去调用接口的情况是非常熟悉的。有很多人都知道, 比如一些用于测试http接口的工具库或者框架都是在它的基础上面开发出来的, 不过今天要跟大家介绍的则是另外一款专门用来测试http接口的框架, 也就是我们所说的这个httpx。
它的API和高度一致。
:
安装:
> pip install httpxhttpx 简单使用
当然, 这个情况是不支持x这个形式的。
import httpxr = httpx.get("http://httpbin.org/get")
print(r.status_code)
print(r.json())
执行结果:
200{'args': {}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Host': 'httpbin.org', 'User-Agent': 'python-httpx/0.12.1', 'X-Amzn-Trace-Id': 'Root=1-5ea5b58c-e446c44392ea090809e8a4bc'}, 'origin': '113.97.33.224', 'url': 'http://httpbin.org/get'}
import httpxpayload = {'key1': 'value1', 'key2': 'value2'}
r = httpx.post("http://httpbin.org/post", data=payload)
print(r.json())
执行结果:
{'args': {}, 'data': '', 'files': {}, 'form': {'key1': 'value1', 'key2': 'value2'}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Content-Length': '23', 'Content-Type': 'application/x-www-form-urlencoded', 'Host': 'httpbin.org', 'User-Agent': 'python-httpx/0.12.1', 'X-Amzn-Trace-Id': 'Root=1-5ea5b61d-1871d10e80b8324e48ea475e'}, 'json': None, 'origin': '113.97.33.224', 'url': 'http://httpbin.org/post'}你会察觉到这实际上几乎是完全相同的状况, 不同的主要点在于,这里已经把原先的某个元素替换成了httpx这个内容。
在进行异步调用的时候, 我们会用到httpx。
我们接下来要去认识一下httpx这个工具的异步调用这一回事。
import httpximport asyncio
async def main():
async with httpx.AsyncClient() as client:
resp = await client.get('http://httpbin.org/get')
result = resp.json()
print(result)
asyncio.run(main())
此处实际应用了async以及await等功能模块, 关于这些异步相关内容的更多详情, 您可以参考我此前所撰写的有关异步I/O基础概念的入门介绍部分。
异步的这种调用方式, 它的优势在哪里呢?
我们发现, 要是采用异步的话, 接口调用会变得更复杂一些, 那为啥还要用异步呢? 当你需要去调用1000次接口的时候, 异步调用可以让你的整体速度变快。接下来我们通过一个简单的例子来做个对比看看。
以我flask开发的简单接口为例子:
为了使得测试工作的过程能够获得更加准确的结论, 我所采取的具体措施是将flask服务直接部署在了另一台计算机设备上面, 这一操作实现了测试机与被测服务之间的相互分离状态。
# 同步调用import time
import httpx
def make_request(client):
resp = client.get('http://192.168.0.7:5000')
result = resp.json()
# print(result)
assert result["code"] == 10200
def main():
session = httpx.Client()
# 1000 次调用
for _ in range(1000):
make_request(session)
if __name__ == '__main__':
# 开始
start = time.time()
main()
# 结束
end = time.time()
print(f'同步:发送1000次请求,耗时:{end - start}')
结果:
...同步:发送1000次请求,耗时:52.948561906814575
# 异步调用import httpx
import asyncio
import time
async def request(client):
resp = await client.get('http://192.168.0.7:5000')
result = resp.json()
# print(result)
assert result["code"] == 10200
async def main():
async with httpx.AsyncClient() as client:
# # 开始
# start = time.time()
# 1000 次调用
task_list = []
for _ in range(1000):
req = request(client)
task = asyncio.create_task(req)
task_list.append(task)
await asyncio.gather(*task_list)
if __name__ == "__main__":
#开始
start = time.time()
asyncio.run(main())
# 结束
end = time.time()
print(f'异步:发送1000次请求,耗时:{end - start}')
结果:
...异步:发送1000次请求,耗时:3.903275728225708
把httpx拿来用作发起请求的工具的话, 同步方式的请求体验和异步方式的请求体验之间的区别, 那真是相当的大。
以上的这些例句, 目前已经放置到了-API-test这个项目里面去了。
总结
* 这里只是为了拿非异步框架的 flask 当作接口服务端来进行对比, 如果把接口服务同样更换成前面介绍的 snaic 异步框架的话, 上面这两组测试对比就不那么明显了, 因为 snaic 的异步接口服务在处理同步请求方面会更快一些, 我们在安装 snaic 的时候就会发现的, 它也同样集成了 httpx 这个库。
为什么要学习异步技术, 因为在我们公司之中存在大量的接口采用了异步调用这一方式。所以我希望可以把这个概念真正地搞清楚明白, 理由就是这么简单直接。一定要保持在工作中对于相关技术知识的好奇心。
拿在火车站买票这个场景来说, 火车站本身被视为一个进程, 而售票窗。