协程
一、协程
协程,又称微线程,纤程,也称为用户级线程,在不开辟线程的基础上完成多任务,也就是在单线程的情况下完成多任务,多个任务按照一定顺序交替执行
1、单线程+异步协程(遇到Io阻塞会自动切换,利用阻塞时间就去执行其他任务)
在几个进程之间随意切换单个任务
实现协程的方法;
greenlet 早前模块
yield关键字
asyncio装饰器(Python3.4)
async & await关键字(Python3.5) (推荐)
2、异步编程
1.事件循环
理解成一个死循环,去检测并执行某些代码,就是无限循环的做任务列表中的任务,直到任务做完为止
2.生成事件循环:
去生成或者获取一个事件
loop = asyncio.get_event_loop()
将任务放到任务列表
loop.run_until_complete(任务)
3、解释
协程函数:定义函数时前面加一个async
async def func():
协程对象:执行协程函数()得到的协程对象
result = func()
#### 执行协程函数,创建协程对象,函数内部代码都不会执行
执行:
import asyncio
async def func():
print("1234")
result = func()
#协程对象交给事件循环来处理才会执行
loop = asyncio.get_event_loop()
loop.run_until_complete(result)
#在python3.7以后执行:就是把上面两句话转为下面一句话
asyncio.run(result)
4、await关键字
await后面要跟可等待对象(协程对象、future、task对象),即io等待
await asyncio.sleep(2) #后面跟一个io等待对象
await就是等待对象,直到这个对象得到值以后才开始执行
5、task对象
事件循环中可以添加多个任务,用于并发调度协程
创建task对象
task1 = asyncio.create_task(协程函数) #python3.7以后
task1 = asyncio.ensure_future(协程函数) #Python3.7以前
现在使用:
import asyncio
async def func1(): #async就可以定义协程
print(1)
await asyncio.sleep(2) #遇到Io耗时操作时,就会切换到tasks中的其他任务
return '返回值'
async def main():
print(3)
tasks = [
asyncio.create_task(func1(),name='n1'), #拿到返回值才会执行
asyncio.create_task(func1(),name='n2') #拿到返回值才会执行
]
print(2)
done,pending = await asyncio.wait(tasks,timeout=None)
#timeout=None表示最多等待多少时间,done是所有函数返回结果,是一个集合,而pending表示最大等待时间完了后,还未完成的任务
asyncio.run(main())
6、asyncio.future对象(一般不用)
task继承future对象,task对象内部await结果的处理基于future对象来的
7、concurrent.future对象
使用线程池、进程池实现异步操作时才用得到
import time
from concurrent.future import Future
from concurrent.future.thread import ThreadPoolExecutor
from concurrent.future.thread import ProcessPoolExecutor
def func(value):
time.sleep(2)
print(value)
return 123
#创建线程池
pool = ThreadPoolExecutor(max_workers=5)
#创建进程池
pool = ProcessPoolExecutor(max_workers=5)
for i in range(10):
fut = pool.submit(func,1)
print(fut)
二、yield版本
import time def work1(): while True: print("work1") yield time.sleep(0.5) def work2(): while True: print("work2") yield time.sleep(0.5) def main(): w1 = work1() w2 = work2() while True: #无限循环 next(w1) #开启协程 next(w2) if __name__ == "__main__": main()
三、greenlet
python中的greenlet模块对其封装,从而使得切换任务变的更加简单
先安装模块
pip3 install greenlet
代码实例
import time import greenlet # 任务1 def work1(): for i in range(3): print("work1") time.sleep(1) # 切换到协程2里面执行对应的任务 g2.switch() # 任务2 def work2(): for i in range(3): print("work2") time.sleep(1) # 切换到第一个协程执行对应的任务 g1.switch() if __name__ == '__main__': # 创建协程指定对应的任务 g1 = greenlet.greenlet(work1) g2 = greenlet.greenlet(work2) # 切换到第一个协程执行对应的任务 g1.switch()
四、gevent
相较于greenlet,这个gevent可以自动切换
同上先安装包
import gevent def work(n): for i in range(n): # 获取当前协程 print(gevent.getcurrent(), i) #用来模拟一个耗时操作,注意不是time模块中的sleep gevent.sleep(1) g1 = gevent.spawn(work, 3) g2 = gevent.spawn(work, 3) g3 = gevent.spawn(work, 3) g1.join() g2.join() g3.join()

浙公网安备 33010602011771号