asyncio

打印 上一主题 下一主题

主题 543|帖子 543|积分 1629

asyncio还是一个python的单进程单线程程序,比较适合处理那些需要等待的任务。比如网络通信。
async的核心是一个事件循环event loop。event loop控制着任务的调度运行。同时执行的任务只有一个不存在系统级上下文切换和线程不一样。需要每个task告知event loop 运行完成可以让其他task运行。不存在竞争冒险问题,可以名确知道每个task什么时候停止运算。
coroutine


  • coroutine function:由async修饰的函数
  1. async def func():
  2.     pass
复制代码

  • 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 是阻塞运行的,直到执行的协程完成后才返回
  1. import asyncio
  2. async def coru_f(i):
  3.     await asyncio.sleep(1)
  4.     return i
  5. async def coroutine_function(index):
  6.     print(f"coroutine {index} start")
  7.     var = await coru_f(index)
  8.     # await把coroutine object转换为一个新的task,并向event loop注册这个task
  9.     # 并告诉event loop 需要等待后面的新的task运行完才会继续运行当前task
  10.     # 然后在当前task等待新task运行完成时,event loop 会运行其他task
  11.     # 当event loop再次调度运行这个task值时,会获取新的task的返回值
  12.     # 并将其赋值给var
  13.     print(var)
  14.     print(f"exit coroutine {index}")
  15. async def main():
  16.     await coroutine_function(1)
  17.     await coroutine_function(2)
  18. if __name__ == "__main__":
  19.     coroutine_obj = main()
  20.     # 创建event loop,把coroutine object转换成task,然后运行task
  21.     asyncio.run(coroutine_obj)  # asyncio.run是串行执行
  22.    
复制代码
asyncio.creat_task

asyncio.run和await只能串行执行,asyncio.creat_task同样接收一个coroutine object,会把coroutine object 转换为一个task,返回这个task并且向event loop注册这个task
  1. import asyncio
  2. import time
  3. async def cor_fun(delay, string, index):
  4.     print(f"task{index} started at {time.strftime('%X')}")
  5.     await asyncio.sleep(delay) # 告诉event loop需要等待asyncio.sleep(delay) 运行完成,控制权交回给event loop, event loop就会调度其他task运行
  6.     print(string)
  7.     print(f"task{index} finished at {time.strftime('%X')}\n")
  8. async def main():
  9.     task1 = asyncio.create_task(
  10.         cor_fun(1, "hello", 1)
  11.     )  # 创建task并不会把控制权交回给event loop,所以不会调度运行新建的task,会继续运行main这个coroutine function的代码
  12.     task2 = asyncio.create_task(
  13.         cor_fun(2, "world", 2)
  14.     )
  15.     print(f"started at {time.strftime('%X')}\n")
  16.     await task1 # 告诉event loop需要等待task1 运行完成,控制权交回给event loop, event loop就会调度其他task运行
  17.     await task2
  18.     print(f"finished at {time.strftime('%X')}\n")
  19. asyncio.run(main())
  20. # started at 23:52:09
  21. # task1 started at 23:52:09
  22. # task2 started at 23:52:09
  23. # hello
  24. # task1 finished at 23:52:10
  25. # world
  26. # task2 finished at 23:52:11
  27. # finished at 23:52:11
复制代码
asyncio.gather

asyncio.gather接收多个task或coroutine或future,把多个task组合起来,返回一个future对象
  1. import asyncio
  2. import time
  3. from pyrsistent import m
  4. async def sum_(n):
  5.     print(f"calculate 1**3+.....+{n}**3 at {time.strftime('%X')}")
  6.     await asyncio.sleep(n//3)
  7.     ans = sum([i**3 for i in range(1,n+1)])
  8.     print(f"finished calculating 1**3+.....+n**3 at {time.strftime('%X')}")
  9.     return ans
  10. async def main():
  11.     print(f"started at {time.strftime('%X')}")
  12.     res = await asyncio.gather(
  13.         sum_(5),
  14.         sum_(10),
  15.         sum_(3)
  16.     )  
  17.     # future对象也可以await,await futer 告诉event loop 需要等待里面每一个task运行完成
  18.     # 同时把所有task的返回值放到一个list中返回
  19.     print(res)
  20.     print(f"finished at {time.strftime('%X')}")
  21. if __name__ == "__main__":
  22.     asyncio.run(main())
  23.    
  24. # started at 00:08:12
  25. # calculate 1**3+.....+n**3 at 00:08:12
  26. # calculate 1**3+.....+n**3 at 00:08:12
  27. # calculate 1**3+.....+n**3 at 00:08:12
  28. # finished calculating 1**3+.....+n**3 at 00:08:13
  29. # finished calculating 1**3+.....+n**3 at 00:08:13
  30. # finished calculating 1**3+.....+n**3 at 00:08:15
  31. # [225, 3025, 36]
  32. # finished at 00:08:15
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

商道如狼道

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表