Python 协程实现异步
今日主题:前面分享过Python 通过使用回调函数如何实现异步的处理,今天我们将通过一个简单的示例来讲解一下协程是如何实现异步的处理的。
协程的概念
协程,又称微线程,是一种用户态的轻量级线程。协程能保留上一次调用时的状态,每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置,当程序中存在大量不需要CPU的操作时(IO),适用于协程。
协程的优势
协程有极高的执行效率,因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销。
不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。
因为协程是一个线程执行,所以想要利用多核CPU,最简单的方法是多进程+协程,这样既充分利用多核,又充分发挥协程的高效率。
构成协程的条件
-
必须在只有一个单线程里实现并发
-
修改共享数据不需加锁
-
用户程序里自己保存多个控制流的上下文栈
-
一个协程遇到IO操作自动切换到其它协程
Python 使用协程实现异步
import threading
import time
import datetime
#第一个请求
def request_1():
print("the request 1 is start")
data=yield io()#定义一个协程处理
print("the response of callback is:",data)
print("the request 1 is end")
#第二个请求
def request_2():
print("the request 2 is start")
time.sleep(2)#定义耗时2s
print("the request 2 is end")
#获取数据请求类的操作,如:从db读取数据,循环耗时,调用其他api等
def io():
def run():
print("the run is start")
time.sleep(5)#定义耗时5s
print("the run is end")
conn_db=[x for x in range(10000)]#模拟从db获取数据
try:
global gen
gen.send(conn_db)#线程结束时发送数据给request_1函数里面的data=yeild io(),此时request_1被唤醒继续处理
exceptStopIterationas e:
print(e)
# 这里是启动一个线程去处理这个io操作,不用阻塞程序的处理,即不影响requst_2的继续处理
threading.Thread(target=run,).start()
if __name__ =='__main__':
start_time=datetime.datetime.now()
global gen
gen=request_1()#函数的赋值操作,生成一个生成器
next(gen)#调用next函数,预激协程,执行了request_1()函数,如果io被挂起,就直接执行 request_2()
request_2()
end_time=datetime.datetime.now()
#这里是在统计总耗时,从打印的结果可以看到是异步处理的。
print("the spend of total time is:",(end_time-start_time).seconds)
程序运行后的输出是:
the request 1is start
the run is start
the request 2is start
the request 2is end
the spend of total time is:2
the run is end
the response of callback is:[0,1,...9999]
the request 1is end
欢迎关注【无量测试之道】公众号,回复【领取资源】,
Python编程学习资源干货、
Python+Appium框架APP的UI自动化、
Python+Selenium框架Web的UI自动化、
Python+Unittest框架API自动化、
资源和代码 免费送啦~
文章下方有公众号二维码,可直接微信扫一扫关注即可。
备注:我的个人公众号已正式开通,致力于测试技术的分享,包含:大数据测试、功能测试,测试开发,API接口自动化、测试运维、UI自动化测试等,微信搜索公众号:“无量测试之道”,或扫描下方二维码:
添加关注,让我们一起共同成长!
上一篇: js格式化时间戳函数
下一篇: python用gevent实现异步