协程

一、协程

  协程,又称微线程,纤程,也称为用户级线程,在不开辟线程的基础上完成多任务,也就是在单线程的情况下完成多任务,多个任务按照一定顺序交替执行 

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()

 



posted @ 2022-04-01 17:13  新入世界的小白  阅读(77)  评论(0)    收藏  举报