天天看点

Python协程

 Python 3.5以后引入了

async/await

语法定义协程函数,代码如下所示。每个协程函数都以

async

声明,以区别于普通函数,对于耗时的代码或函数我们使用

await

声明,表示碰到等待时挂起,以切换到其它任务。

协程从创建到运行具体步骤

1、async定义协成函数,

2、由协成函数创建协成任务,有三种方式

      
  方法1:使用ensure_future方法。future代表一个对象,未执行的任务。
        task1 = asyncio.ensure_future(func1(1))      
  方法2:使用loop.create_task方法
        task1 = loop.create_task(func1(1))      
方法3:使用Python 3.7提供的asyncio.create_task方法
         task1 = asyncio.create_task(func1(1))

3、收集协程任务列表,
    用 await asyncio.wait(tasks)方法收集协程任务
         asyncio.wait返回两个值:done 和 pending,done 为已完成的协程任务列表,pending 为超时未完成的协程任务类别,
     需通过task.result()方法可以获取每个协程任务返回的结果

    用asyncio.gather方法,比asyncio.wait方法类似,但更强大,列表中传入的不是create_task方法创建的协程任务,它会自动将函数封装成协程任务,返回值也不同
         await asyncio.gather(*tasks),这里*号。gather自动将函数列表封装成了协程任务
         asyncio.gather 返回的是所有已完成协程任务的 result,不需要再进行调用或其他操作,就可以得到全部结果。

    区别:
        gather具有把普通协程函数包装成协程任务的能力,wait没有。wait只能接收包装后的协程任务列表做参数。
        两者返回值不一样,wait返回的是已完成和未完成任务的列表,而gather直接返回协程任务执行结果。
        gather返回的任务执行结果是有序的,wait方法获取的结果是无序的。

      
4、收集协程任务列表或单个协程任务,最后一起交由事件循环执行

    获取事件循环
    loop = asyncio.get_event_loop()
    执行协程任务
    loop.run_until_complete(func1(1))
    关闭事件循环
    loop.close()

    asyncio.run方法,封装了上三步: asyncio.run(func1(1))


5、可以给每个协程任务通过         add_done_callback                方法给单个协程任务添加回调函数,

      
   task.add_done_callback(callback)      
asyncio.wait用法,获取结果

      
#-*- coding:utf-8 -*-
 import asyncio
 
 async def func1(i):
     print(f"协程函数{i}马上开始执行。")
     await asyncio.sleep(2)
     return i
 
 # 回调函数
 def callback(future):
     print(f"执行结果:{future.result()}")
 
 async def main():
     tasks = []
     for i in range(1, 5):
         task = asyncio.create_task(func1(i))
         
         # 注意这里,增加回调函数
         task.add_done_callback(callback)
         tasks.append(task)

     #timeout选项设置任务切换前单个任务最大等待时间长度
     await asyncio.wait(tasks, timeout=10)      
   
 if __name__ == '__main__':
     asyncio.run(main())      
asyncio.gather用法,获取结果

      
#-*- coding:utf-8 -*-
 import asyncio
 
 async def func1(i):
     print(f"协程函数{i}马上开始执行。")
     await asyncio.sleep(2)
     return i
 

      
def callback(future):
     print(f"执行结果:{future.result()}"      
async def main():
     tasks = []
     for i in range(1, 5):
         tasks.append(func1(i))
 
     results = await asyncio.gather(*tasks)
     for result in results:
         print(f"执行结果: {result}")
 
 if __name__ == '__main__':
     asyncio.run(main())      

其他: