Python Asyncio介绍

296 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情

介绍

Python3.4之前官方未提供协程的类库,一般使用gevent实现协程达到异步编程的目的。

Python3.4之后官方推出asyncio模块,有如下几个特点:

  • 单线程
  • 事件循环
  • 适用于IO密集型场景

示例:通过asyncio实现协程

 import asyncio
 ​
 ​
 @asyncio.coroutine
 def f1():
     print(1)
     yield from asyncio.sleep(2)     # 遇到IO睡2s
     print(2)
 ​
 ​
 @asyncio.coroutine
 def f2():
     print(3)
     yield from asyncio.sleep(2)     # 遇到IO睡2s
     print(4)
 ​
 ​
 tasks = [
     asyncio.ensure_future(f1()),
     asyncio.ensure_future(f2())
 ]
 ​
 loop = asyncio.get_event_loop()                 # 得到一个事件循环
 loop.run_until_complete(asyncio.wait(tasks))    # 等待所有任务执行完毕
 # 打印结果:1 3 -睡2s- 2 4
  • 注意1:asyncio内部是基于yield实现的协程,本质上在事件循环内切换执行任务。
  • 注意2:@asyncio.coroutine这个装饰器在python3.8中将会被弃用,推荐使用async def

async/await实现协程

  • Python3.5官方推出 asyncawait关键字,目的是让协程代码可以更加简洁。
 import asyncio
 ​
 ​
 async def f1():
     print(1)
     await asyncio.sleep(2)      # 等 可以等待的对象
     print(2)
 ​
 ​
 async def f2():
     print(3)
     await asyncio.sleep(2)
     print(4)
 ​
 ​
 tasks = [
     asyncio.ensure_future(f1()),
     asyncio.ensure_future(f2())
 ]
 ​
 loop = asyncio.get_event_loop()
 loop.run_until_complete(asyncio.wait(tasks))
 # 打印结果:1 3 -睡2s- 2 4
  • 注意1:await只能用在async def 内,但在ipython中可以直接使用

补充知识点

  • 使用async def定义的函数叫协程函数
  • 协程函数加括号不会执行函数内部代码,而是得到一个协程对象
  • 协程对象需要配合事件循环才可以执行内部代码
  • 创建的事件循环的方式特别方便 loop = asyncio.get_event_loop()
  • 运行事件循环:loop.run_until_complete(asyncio.wait(tasks))
  • Python3.8以后提供了一个快捷方法可以快速创建事件循环并运行:asyncio.run()
  • 官方提供的事件循环效率不如第三方事件循环uvloop,使用uvloop也比较方便
 # 安装uvloop
 pip install uvloop   # 可惜!!!windows不支持
 ​
 ​
 # uvloop替换官方事件循环的3种方式
 # 方式1
 import asyncio
 import uvloop
 asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
 ​
 # 方式2 uvloop.install()
 ​
 ​
 # 方式3
 import asyncio
 import uvloop
 loop = uvloop.new_event_loop()
 asyncio.set_event_loop(loop)