最近公司  Python 后端我的项目进行重构,整个后端逻辑根本都变更为采纳"异步"协程的形式实现。看着满屏幕通过 async await(协程在 Python 中的实现)润饰的代码,我登时感到一脸懵逼,手足无措。

尽管之前有理解过"协程"是什么货色,但并没有深刻摸索,于是正好借着这次机会能够好好学习一下。

什么是协程?

简略来说,协程是一种基于线程之上,但又比线程更加轻量级的存在。对于零碎内核来说,协程具备不可见的个性,所以这种由 程序员本人写程序来治理 的轻量级线程又常被称作 "用户空间线程"。

协程比多线程好在哪呢?

  1. 线程的控制权在操作系统手中,而 协程的控制权齐全把握在用户本人手中,因而利用协程能够缩小程序运行时的上下文切换,无效进步程序运行效率。
  2. 建设线程时,零碎默认调配给线程的 栈 大小是 1 M,而协程更轻量,靠近 1 K 。因而能够在雷同的内存中开启更多的协程。
  3. 因为协程的实质不是多线程而是单线程,所以不须要多线程的锁机制。因为只有一个线程,也不存在同时写变量而引起的抵触。在协程中管制共享资源不须要加锁,只须要判断状态即可。所以协程的执行效率比多线程高很多,同时也无效防止了多线程中的竞争关系。

协程的实用 & 不实用场景

实用场景:协程实用于被阻塞的,且须要大量并发的场景。

不实用场景:协程不适用于存在大量计算的场景(因为协程的实质是单线程来回切换),如果遇到这种状况,还是应该应用其余伎俩去解决。

初探异步 http 框架 httpx

至此咱们对 "协程" 应该有了个大略的理解,但故事说到这里,置信有敌人还是满脸疑难:"协程" 对于接口测试有什么帮忙呢?不要焦急,答案就在上面。

置信用过 Python 做接口测试的敌人都对 requests 库不生疏。requests 中实现的 http 申请是同步申请,但其实基于 http 申请 IO 阻塞的个性,非常适合用协程来实现 "异步" http 申请从而晋升测试效率。

置信早就有人留神到了这点,于是在 Github 通过了一番摸索后,果不其然,最终寻找到了反对协程 "异步" 调用 http 的开源库: httpx

什么是 httpx

httpx 是一个简直继承了所有 requests 的个性并且反对 "异步" http 申请的开源库。简略来说,能够认为 httpx 是强化版 requests。

上面大家能够跟着我一起见识一下 httpx 的弱小

装置

httpx 的装置非常简单,在 Python 3.6 以上的环境执行

pip install httpx

最佳实际

俗话说得好,效率决定成败。我别离应用了 httpx 异步 和 同步 的形式对批量 http 申请进行了耗时比拟,来一起看看后果吧~

首先来看看同步 http 申请的耗时体现:

import asyncioimport httpximport threadingimport timedef sync_main(url, sign):    response = httpx.get(url).status_code        print(f'sync_main: {threading.current_thread()}: {sign}2 + 1{response}')sync_start = time.time()[sync_main(url='http://www.baidu.com', sign=i) for i in range(200)]sync_end = time.time()print(sync_end - sync_start)

代码比较简单,能够看到在 sync_main 中则实现了同步 http 拜访百度 200 次。

运行后输入如下(截取了局部要害输入...):

sync_main: <_MainThread(MainThread, started 4471512512)>: 192: 200sync_main: <_MainThread(MainThread, started 4471512512)>: 193: 200sync_main: <_MainThread(MainThread, started 4471512512)>: 194: 200sync_main: <_MainThread(MainThread, started 4471512512)>: 195: 200sync_main: <_MainThread(MainThread, started 4471512512)>: 196: 200sync_main: <_MainThread(MainThread, started 4471512512)>: 197: 200sync_main: <_MainThread(MainThread, started 4471512512)>: 198: 200sync_main: <_MainThread(MainThread, started 4471512512)>: 199: 20016.56578803062439

能够看到在下面的输入中, 主线程没有进行切换(因为原本就是单线程啊喂!)申请依照程序执行(因为是同步申请)。

程序运行共耗时 16.6 秒

上面咱们试试 "异步" http 申请:

import asyncioimport httpximport threadingimport timeclient = httpx.AsyncClient()async def async_main(url, sign):    response = await client.get(url)    status_code = response.status_code    print(f'async_main: {threading.current_thread()}: {sign}:{status_code}')loop = asyncio.get_event_loop()tasks = [async_main(url='http://www.baidu.com', sign=i) for i in range(200)]async_start = time.time()loop.run_until_complete(asyncio.wait(tasks))async_end = time.time()loop.close()print(async_end - async_start)

上述代码在 async_main 中用 async await 关键字实现了"异步" http,通过 asyncio ( 异步 io 库申请百度首页 200 次并打印出了耗时。

运行代码后能够看到如下输入(截取了局部要害输入...)

async_main: <_MainThread(MainThread, started 4471512512)>: 56: 200async_main: <_MainThread(MainThread, started 4471512512)>: 99: 200async_main: <_MainThread(MainThread, started 4471512512)>: 67: 200async_main: <_MainThread(MainThread, started 4471512512)>: 93: 200async_main: <_MainThread(MainThread, started 4471512512)>: 125: 200async_main: <_MainThread(MainThread, started 4471512512)>: 193: 200async_main: <_MainThread(MainThread, started 4471512512)>: 100: 2004.518340110778809

能够看到程序尽管是乱的(56,99,67...) (这是因为程序在协程间不停切换) 然而主线程并没有切换 (协程实质还是单线程 )。

程序共耗时 4.5 秒

比起同步申请耗时的 16.6 秒 缩短了靠近 73 %!

俗话说得好,一步快,步步快。 在耗时方面,"异步" http 的确比同步 http 快了很多。当然,"协程" 不仅仅能在申请效率方面赋能接口测试, 把握 "协程"后,置信小伙伴们的技术水平也能晋升一个台阶,从而设计出更优良的测试框架。

以上就是本次分享的所有内容,如果你感觉文章还不错,欢送关注公众号:Python编程学习圈,每日干货分享,发送“J”还可支付大量学习材料,内容笼罩Python电子书、教程、数据库编程、Django,爬虫,云计算等等。或是返回编程学习网,理解更多编程技术常识。