Python协程asyncio|Python协程asyncio 异步编程笔记分享
目录
- 1.事件循环
- 2.协程和异步编程
- 2.1 基本使用
- 2.2 await
- 2.3 Task对象
1.事件循环 可以理解成为一个死循环,去检查任务列表中的任务,如果可执行就去执行,如果检查不到就是不可执行的,那就忽略掉去执行其他可执行的任务,如果IO结束了(比如说去百度下载图片,下载完了就会变成可执行任务)再去执行下载完成之后的逻辑
#这里的任务是有状态的,比如这个任务已经完成或者正在执行或者正在IO等待任务列表 = [ 任务1, 任务2, 任务3,... ]while True:可执行的任务列表,已完成的任务列表 = 去任务列表中检查所有的任务,将'可执行'和'已完成'的任务返回for 就绪任务 in 可执行的任务列表:执行已就绪的任务for 已完成的任务 in 已完成的任务列表:在任务列表中移除 已完成的任务如果 任务列表 中的任务都已完成,则终止循环
#在编写程序时候可以通过如下代码来获取和创建事件循环。import asyncioloop = asyncio.get_event_loop()#将任务放到任务列表,让事件循环去检测任务的状态(是否可运行,是否IO)loop.loop.run_until_complete(任务)
2.协程和异步编程 协程函数,定义形式为 async def 的函数。
协程对象,调用 协程函数() 所返回的对象。
# 定义一个协程函数async def func():pass# 调用协程函数,返回一个协程对象(内部代码不会执行)result = func()
2.1 基本使用
程序中,如果想要执行协程函数的内部代码,需要 事件循环 和 协程对象 配合才能实现
示例1:
import asyncioasync def func():print("协程内部代码")# 调用协程函数,返回一个协程对象。result = func()# 方式一# loop = asyncio.get_event_loop() # 创建一个事件循环# loop.run_until_complete(result) # 将协程当做任务提交到事件循环的任务列表中,协程执行完成之后终止。# 方式二# 本质上方式一是一样的,内部先 创建事件循环 然后执行 run_until_complete,一个简便的写法。# asyncio.run 函数在 Python 3.7 中加入 asyncio 模块,asyncio.run(result)
2.2 await
await+可等待对象(协程对象,Future,Task对象)
await是一个只能在协程函数中使用的关键字,用于遇到IO操作时挂起 当前协程(任务),当前协程(任务)挂起过程中 事件循环可以去执行其他的协程(任务),当前协程IO处理完成时,可以再次切换回来执行await之后的代码。
import asyncioasync def func():print("执行协程函数内部代码")# 遇到IO操作挂起当前协程(任务),等IO操作完成之后再继续往下执行。# 当前协程挂起时,事件循环可以去执行其他协程(任务)。 #response是IO耗时结束后拿到的结果response = await asyncio.sleep(2)print("IO请求结束,结果为:", response)result = func()asyncio.run(result)
结果示例2:
执行协程函数内部代码
IO请求结束,结果为: None
#这里返回None表示这个好事没有啥意义,如果你是下载了一张图片成功后会返回一个结果
import asyncioasync def others():print("start")await asyncio.sleep(2)print('end')return '返回值'async def func():print("执行协程函数内部代码")# 遇到IO操作挂起当前协程(任务),等IO操作完成之后再继续往下执行。当前协程挂起时,事件循环可以去执行其他协程(任务)。response = await others()print("IO请求结束,结果为:", response)asyncio.run( func() )
执行结果:示例3:
执行协程函数内部代码
start
end
IO请求结束,结果为: 返回值
import asyncioasync def others():print("start")await asyncio.sleep(2)print('end')return '返回值'async def func():print("执行协程函数内部代码")# 遇到IO操作挂起当前协程(任务),等IO操作完成之后再继续往下执行。当前协程挂起时,事件循环可以去执行其他协程(任务)。#await等待有返回值才会向下执行response1 = await others()print("IO请求结束,结果为:", response1)response2 = await others()print("IO请求结束,结果为:", response2)asyncio.run( func() )
执行结果:下一步依赖上一步的结果时使用await,但如果有其他任务依然会切换到其他任务去执行
执行协程函数内部代码
start
end
IO请求结束,结果为: 返回值
start
end
IO请求结束,结果为: 返回值
2.3 Task对象
在事件循环中添加多个任务。
Tasks用于并发调度协程,通过asyncio.create_task(协程对象)的方式创建Task对象,这样可以让协程加入事件循环中等待被调度执行。除了使用 asyncio.create_task() 函数以外,还可以用低层级的 loop.create_task() 或 ensure_future() 函数。不建议手动实例化 Task 对象。
本质上是将协程对象封装成task对象,并将协程立即加入事件循环,同时追踪协程的状态。
注意:asyncio.create_task() 函数在 Python 3.7 中被加入。在 Python 3.7 之前,可以改用低层级的 asyncio.ensure_future() 函数。
示例1:
import asyncioasync def func():print(1)await asyncio.sleep(2)print(2)return "返回值"async def main():print("main开始")# 创建协程,将协程封装到一个Task对象中并立即添加到事件循环的任务列表中,等待事件循环去执行(默认是就绪状态)。task1 = asyncio.create_task(func())# 创建协程,将协程封装到一个Task对象中并立即添加到事件循环的任务列表中,等待事件循环去执行(默认是就绪状态)。task2 = asyncio.create_task(func())print("main结束")# 当执行某协程遇到IO操作时,会自动化切换执行其他任务。# 此处的await是等待相对应的协程全都执行完毕并获取结果ret1 = await task1ret2 = await task2print(ret1, ret2)asyncio.run(main())
执行结果:实例2:
main开始
main结束
1
1
2
2
返回值 返回值
import asyncioasync def func():print(1)await asyncio.sleep(2)print(2)return "返回值"async def main():print("main开始")# 创建协程,将协程封装到Task对象中并添加到事件循环的任务列表中,等待事件循环去执行(默认是就绪状态)。# 在调用task_list = [asyncio.create_task(func(), name="n1"),asyncio.create_task(func(), name="n2")]print("main结束")# 当执行某协程遇到IO操作时,会自动化切换执行其他任务。# 此处的await是等待所有协程执行完毕,并将所有协程的返回值保存到done# 如果设置了timeout值,则意味着此处最多等待的秒,完成的协程返回值写入到done中,未完成则写到pending中(比如下面的Timeout=1,要下载的图片是两秒,设为1秒就会执行失败,done内为空,而pending中就是执行失败的)。done, pending = await asyncio.wait(task_list, timeout=None)print(done, pending)asyncio.run(main())执行结果:main开始main结束1122{result='返回值'>, result='返回值'>} set()
示例3:
import asyncioasync def func():print("执行协程函数内部代码")# 遇到IO操作挂起当前协程(任务),等IO操作完成之后再继续往下执行。当前协程挂起时,事件循环可以去执行其他协程(任务)。response = await asyncio.sleep(2)print("IO请求结束,结果为:", response)coroutine_list = [func(), func()]# 错误:coroutine_list = [ asyncio.create_task(func()), asyncio.create_task(func()) ]# 此处不能直接 asyncio.create_task,因为将Task立即加入到事件循环的任务列表,# 但此时事件循环还未创建,所以会报错。# 使用asyncio.wait将列表封装为一个协程,并调用asyncio.run实现执行两个协程# asyncio.wait内部会对列表中的每个协程执行ensure_future,封装为Task对象。done,pending = asyncio.run( asyncio.wait(coroutine_list) )
【Python协程asyncio|Python协程asyncio 异步编程笔记分享】以上就是Python协程asyncio 异步编程笔记分享的详细内容,更多关于Python协程asyncio 异步编程的资料请关注脚本之家其它相关文章!
推荐阅读
- python学习之|python学习之 实现QQ自动发送消息
- 逻辑回归的理解与python示例
- python自定义封装带颜色的logging模块
- 【Leetcode/Python】001-Two|【Leetcode/Python】001-Two Sum
- Python基础|Python基础 - 练习1
- Python爬虫|Python爬虫 --- 1.4 正则表达式(re库)
- 使用协程爬取网页,计算网页数据大小
- Python(pathlib模块)
- python青少年编程比赛_第十一届蓝桥杯大赛青少年创意编程组比赛细则
- Python数据分析(一)(Matplotlib使用)