在了解了 Python 并发编程的多线程和多进程之后,我们来了解一下基于 asyncio 的异步IO编程--协程
协程简介
协程(Coroutine)又称微线程、纤程,协程不是进程或线程,其执行过程类似于 Python 函数调用,Python 的 asyncio 模块实现的异步IO编程框架中,协程是对使用 async 关键字定义的异步函数的调用;
一个进程包含多个线程,类似于一个人体组织有多种细胞在工作,同样,一个程序可以包含多个协程。多个线程相对独立,线程的切换受系统控制。同样,多个协程也相对独立,但是其切换由程序自己控制。
一个简单例子
我们来使用一个简单的例子了解协程,首先看看下面的代码:
import time
def display(num):
time.sleep(1)
print(num)
for num in range(10):
display(num)
很容易看得懂,程序会输出0到9的数字,每隔1秒中输出一个数字,因此整个程序的执行需要大约10秒 时间。值得注意的是,因为没有使用多线程或多进程(并发),程序中只有一个执行单元(只有一个线程在 执行),而 time.sleep(1) 的休眠操作会让整个线程停滞1秒钟,
对于上面的代码来说,在这段时间里面 CPU是闲置的没有做什么事情。
我们再来看看使用协程会发生什么:
import asyncio
async def display(num): # 在函数前使用async关键字,变成异步函数
await asyncio.sleep(1)
print(num)
异步函数不同于普通函数,调用普通函数会得到返回值,而调用异步函数会得到一个协程对象。我们需要将协程对象放到一个事件循环中才能达到与其他协程对象协作的效果,因为事件循环会负责处理子程 序切换的操作。
简单的说就是让阻塞的子程序让出CPU给可以执行的子程序。
基本概念
异步IO是指程序发起一个IO操作(阻塞等待)后,不用等IO操作结束,可以继续其它操作;做其他事情,当IO操作结束时,会得到通知,然后继续执行。异步IO编程是实现并发的一种方式,适用于IO密集型任务
Python 模块 asyncio 提供了一个异步编程框架,全局的流程图大致如下:
下面对每个函数都从代码层面进行介绍
async
: 定义一个方法(函数),这个方法在后面的调用中不会被立即执行而是返回一个协程对象;
async def test(): print('hello 异步')
test() # 调用异步函数
# 输出:RuntimeWarning: coroutine 'test' was never awaited
coroutine
: 协程对象,也可以将协程对象添加到时间循环中,它会被事件循环调用;
async def test():
print('hello 异步')
c = test() # 调用异步函数,得到协程对象-->c
print(c)
输出:<coroutine object test at 0x0000023FD05AA360>
event_loop
: 事件循环,相当于一个无限循环,可以把一些函数添加到这个事件中,函数不会立即执行, 而是满足某些条件的时候,函数就会被循环执行;
import asyncio
async def test():
print('hello 异步')
c = test() # 调用异步函数,得到协程对象-->c
loo