持续创作,加速成长!这是我参与「掘金日新计划 · 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官方推出
async和await关键字,目的是让协程代码可以更加简洁。
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)