• Python中协程异步IO(asyncio)理解与入门


     1、asyncio

    1. import asyncio
    2. # coroutine function: async开头的函数
    3. async def main():
    4. print('hello')
    5. await asyncio.sleep(1)
    6. print('world')
    7. coro = main() # coroutine object:协程对象
    8. # 当生成协程对象的时候,并不运行函数里面的程序。
    9. # 运行时需要两步走:进入 async 模式、把coroutine变成task
    10. asyncio.run(coro) # 创建 event loop 来跑 task

    2、了解 await 作用

    1. import asyncio
    2. import time
    3. async def say_after(delay, what):
    4. await asyncio.sleep(delay)
    5. print(what)
    6. async def main():
    7. print(f"started at {time.strftime('%X')}")
    8. await say_after(1, 'hello') # await 把控制权交还给 event loop
    9. await say_after(2, 'world')
    10. print(f"finished at {time.strftime('%X')}") # 总共花了3秒
    11. coro = main() # coroutine object:协程对象
    12. asyncio.run(coro) # 创建 event loop 来跑 task

     

    3、了解 asyncio.create_task

    1. import asyncio
    2. import time
    3. async def say_after(delay, what):
    4. await asyncio.sleep(delay)
    5. print(what)
    6. async def main():
    7. task1 = asyncio.create_task(say_after(1, 'hello'))
    8. task2 = asyncio.create_task(say_after(2, 'world'))
    9. # create_task 可提前创建好 task
    10. # 到目前为止,两个 task 都已初始化到 event loop 里面了
    11. print(f"started at {time.strftime('%X')}")
    12. await task1
    13. await task2
    14. print(f"finished at {time.strftime('%X')}")
    15. '''
    16. task1 执行1s等待的时候,event loop 是空闲的,
    17. 它发现 task2 可以执行,就执行了一秒task2,
    18. 所以当 task1 执行完之后,task2 还剩下1秒等待需要执行,所以总体时间花了2秒
    19. async 很适合解决网络通讯的问题,因为网络通讯很多时间是在等待上的,也就是所谓的 io bound task。
    20. 等待的时间,可以去完成别的 task
    21. '''
    22. asyncio.run(main())

    4、协程返回值怎么获取?

    1. import asyncio
    2. import time
    3. async def say_after(delay, what):
    4. await asyncio.sleep(delay)
    5. return f"{what} - {delay}"
    6. async def main():
    7. task1 = asyncio.create_task(say_after(1, 'hello'))
    8. task2 = asyncio.create_task(say_after(2, 'world'))
    9. print(f"started at {time.strftime('%X')}")
    10. ret1 = await task1 # 拿到返回值
    11. ret2 = await task2
    12. print(ret1)
    13. print(ret2)
    14. print(f"finished at {time.strftime('%X')}")
    15. asyncio.run(main())

    5、了解 asyncio.gather

    1. import asyncio
    2. import time
    3. async def say_after(delay, what):
    4. await asyncio.sleep(delay)
    5. return f"{what} - {delay}"
    6. async def main():
    7. task1 = asyncio.create_task(say_after(1, 'hello'))
    8. task2 = asyncio.create_task(say_after(2, 'world'))
    9. print(f"started at {time.strftime('%X')}")
    10. # asyncio.gather的参数可以是若干个协程对象,task,以及asyncio.gather的返回值
    11. # 如果参数是协程对象,它会自动给转化为task
    12. # 最终返回一个list:['hello - 1', 'world - 2']
    13. ret = await asyncio.gather(task1, task2)
    14. print(ret)
    15. print(f"finished at {time.strftime('%X')}")
    16. asyncio.run(main())

    6、了解 asyncio.gather 之后优化一下代码

    1. import asyncio
    2. import time
    3. async def say_after(delay, what):
    4. await asyncio.sleep(delay)
    5. return f"{what} - {delay}"
    6. async def main():
    7. print(f"started at {time.strftime('%X')}")
    8. # 直接将协程对象放到 asyncio.gather 中,它会自动变为 task,再逐个 await,
    9. # 最后返回一个列表式的结果:['hello - 1', 'world - 2']
    10. # 协程的意义:同一时间只有一个任务在跑,它只是想办法充分利用中间的等待时间
    11. # 协程对象只有变成了 task 才能被执行,
    12. # 而 await 和 gather 都是隐式地将协程对象变成了 task
    13. ret = await asyncio.gather(
    14. say_after(1, 'hello'),
    15. say_after(2, 'world')
    16. )
    17. print(ret)
    18. print(f"finished at {time.strftime('%X')}")
    19. asyncio.run(main())

  • 相关阅读:
    virtualbox报错
    U-Boot 移植深入
    ASP.NET第四章 Response、Request和Server对象
    【论文翻译】2.5PC:一个更快的非阻塞原子提交协议
    夜天之书 #98 Rust 程序库生态合作的例子
    spinal HDL - 11 - 使用状态机语法编写“1001“序列检测
    电子电气架构 --- 关于DoIP的一些闲思 下
    【微服务生态】Docker
    MySQL事务
    Github已经54k个star的Docker,到底是什么?
  • 原文地址:https://blog.csdn.net/m0_37738114/article/details/133754188