asyncio还是一个python的单进程单线程程序,比较适合处理那些需要等待的任务。比如网络通信。
async的核心是一个事件循环event loop。event loop控制着任务的调度运行。同时执行的任务只有一个不存在系统级上下文切换和线程不一样。需要每个task告知event loop 运行完成可以让其他task运行。不存在竞争冒险问题,可以名确知道每个task什么时候停止运算。
coroutine
- coroutine function:由async修饰的函数
- coroutine object: 调用coroutine function的返回结果,但不会运行coroutine function里面的代码。
要想运行coroutine代码,需要进入事件循环,然后把coroutine转换成task
asyncio.run(coroutine object)
- asyncio.run接收一个coroutine object作为参数,建立一个事件循环,把coroutine object转换成一个task并注册到建立的事件循环中。事件循环建立后就会寻找可以运行的task,然后运行coroutine代码
- 不能在 asyncio.run 方法内部中再次调用 asyncio.run 方法,此方法在异步代码中只能被调用一次,否则会抛出 RuntimeError 异常;
- asyncio.run 只能执行 async 函数,不能执行普通函数(普通函数需要包装);
- asyncio.run 是阻塞运行的,直到执行的协程完成后才返回
- import asyncio
- async def coru_f(i):
- await asyncio.sleep(1)
- return i
- async def coroutine_function(index):
- print(f"coroutine {index} start")
- var = await coru_f(index)
- # await把coroutine object转换为一个新的task,并向event loop注册这个task
- # 并告诉event loop 需要等待后面的新的task运行完才会继续运行当前task
- # 然后在当前task等待新task运行完成时,event loop 会运行其他task
- # 当event loop再次调度运行这个task值时,会获取新的task的返回值
- # 并将其赋值给var
- print(var)
- print(f"exit coroutine {index}")
- async def main():
- await coroutine_function(1)
- await coroutine_function(2)
- if __name__ == "__main__":
- coroutine_obj = main()
- # 创建event loop,把coroutine object转换成task,然后运行task
- asyncio.run(coroutine_obj) # asyncio.run是串行执行
-
复制代码 asyncio.creat_task
asyncio.run和await只能串行执行,asyncio.creat_task同样接收一个coroutine object,会把coroutine object 转换为一个task,返回这个task并且向event loop注册这个task- import asyncio
- import time
- async def cor_fun(delay, string, index):
- print(f"task{index} started at {time.strftime('%X')}")
- await asyncio.sleep(delay) # 告诉event loop需要等待asyncio.sleep(delay) 运行完成,控制权交回给event loop, event loop就会调度其他task运行
- print(string)
- print(f"task{index} finished at {time.strftime('%X')}\n")
- async def main():
- task1 = asyncio.create_task(
- cor_fun(1, "hello", 1)
- ) # 创建task并不会把控制权交回给event loop,所以不会调度运行新建的task,会继续运行main这个coroutine function的代码
- task2 = asyncio.create_task(
- cor_fun(2, "world", 2)
- )
- print(f"started at {time.strftime('%X')}\n")
- await task1 # 告诉event loop需要等待task1 运行完成,控制权交回给event loop, event loop就会调度其他task运行
- await task2
- print(f"finished at {time.strftime('%X')}\n")
- asyncio.run(main())
- # started at 23:52:09
- # task1 started at 23:52:09
- # task2 started at 23:52:09
- # hello
- # task1 finished at 23:52:10
- # world
- # task2 finished at 23:52:11
- # finished at 23:52:11
复制代码 asyncio.gather
asyncio.gather接收多个task或coroutine或future,把多个task组合起来,返回一个future对象- import asyncio
- import time
- from pyrsistent import m
- async def sum_(n):
- print(f"calculate 1**3+.....+{n}**3 at {time.strftime('%X')}")
- await asyncio.sleep(n//3)
- ans = sum([i**3 for i in range(1,n+1)])
- print(f"finished calculating 1**3+.....+n**3 at {time.strftime('%X')}")
- return ans
- async def main():
- print(f"started at {time.strftime('%X')}")
- res = await asyncio.gather(
- sum_(5),
- sum_(10),
- sum_(3)
- )
- # future对象也可以await,await futer 告诉event loop 需要等待里面每一个task运行完成
- # 同时把所有task的返回值放到一个list中返回
- print(res)
- print(f"finished at {time.strftime('%X')}")
- if __name__ == "__main__":
- asyncio.run(main())
-
- # started at 00:08:12
- # calculate 1**3+.....+n**3 at 00:08:12
- # calculate 1**3+.....+n**3 at 00:08:12
- # calculate 1**3+.....+n**3 at 00:08:12
- # finished calculating 1**3+.....+n**3 at 00:08:13
- # finished calculating 1**3+.....+n**3 at 00:08:13
- # finished calculating 1**3+.....+n**3 at 00:08:15
- # [225, 3025, 36]
- # finished at 00:08:15
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |