一、定义创建协程
在函数前面加上async关键字,这个函数对象就是一个协程通过isinstance函数,确认他是否为Coroutine类型。
from collections.abc import Coroutine
import asyncio
async def hello(name):
await 1
print("hello",name)
# @asyncio.coroutine
# def hello(name):
# yield from asyncio.sleep(6)
if __name__ == "__main__":
coroutine = hello("World")
print(isinstance(coroutine,Coroutine)) #True
生成器是协程的基础,我们是有办法将一个生成器直接变成协程使用的,如下代码
from collections.abc import Coroutine,Generator
import asyncio
# async def hello(name):
# await 1
# print("hello",name)
@asyncio.coroutine
def hello(name):
yield from asyncio.sleep(6)
if __name__ == "__main__":
coroutine = hello("World")
print(isinstance(coroutine,Generator)) #True
print(isinstance(coroutine,Coroutine)) #False
但注意一点在一个生成器头部用上@asyncio.coroutine装饰器就能把这个生成器标记为协程对象,实际上它本质还是生成器。标记后它实际上可以当成协程使用了。
二、asyncio的几个概念
1、事件循环 ——event_loop:程序开始循环,程序员会把一些函数(协程)注册带事件循环上。当满足事情发生时,调用相应的协程函数。
2、协程——coroutine:协程对象,指一个使用关键字async定义的一个函数,它调用不会立刻执行函数,而是会番回忆和协程对象,协程对象注册到时间循环中,由事件循环调用。
3、future对象:代表将来执行或者没有执行的任务的结果,他和task上没有本质的区别
4、任务——task:一个协程对象就是一个原生的可以挂起的函数,任务则是对协程经一部封装,其中包含任务的各种状态。Task对象是Future的子类,他将coroutine和Future联系在一起,将coroutine封装成一个Future对象。
5、async/await 关键字:python3.5用于定义协程的关键字,async定义一个协程,await用于挂起阻塞的异步调用接口。器作用类似于tield
三、协程如何工作
协程工作流程一般如下:
代码如下:
import asyncio
async def hello(name):
print("hello,",name)
coroutine = hello("python")
loop = asyncio.get_event_loop()
task = loop.create_task(coroutine)
loop.run_until_complete(task)
输出结果:hello, python
四、await与yield对比
await用于挂起阻塞的异步调用接口。器作用在一定程度上类似于yield。这仅仅是效果上一样(都能实现暂停的效果),但是功能上却不兼容。意思是你不能再生成器中使用await,也不能在async定义的协程函数中使用yield。
此外,
我们来验证一下await和yield from可以接future 和协程对象。
我们需要创建一个Coroutine对象和Future对象,应为Task是Future的一个子类,那么我们字需要创建一个task对象即可。代码如下
import asyncio
from collections.abc import Coroutine
from asyncio.futures import Future
async def hello(name):
await asyncio.sleeo(2)
print("hello,",name)
coroutine = hello("python")
task = asyncio.ensure_future(coroutine)
print(isinstance(coroutine,Future))
print(isinstance(coroutine,Coroutine))
print(isinstance(task,Future))
我们来调用一下这两个对象
async def hello(name):
await asyncio.sleeo(2)
print("hello,",name)
async def coroutine1(name,coroutine):
await coroutine
print("coroutine1:",name)
def coroutine2(name,coroutine):
yield from coroutine
print("coroutine2:",name)
async def task1(name,task):
await task
print("task1:",name)
def task2(name,task):
yield from task
print("task2:",name)
if __name__ == "__main__":
coroutine = hello("python")
task = asyncio.ensure_future(coroutine)
c1 = coroutine1("c1",coroutine)
c2 = coroutine2("c2",coroutine)
t1 = task1("t1",task)
t2 = task2("t2",task)
发现并没没有报错。
五、绑定回调函数
异步IO的实现原理,就是在IO高的地方挂起,等IO结束后,在继续执行。在绝大部分时候,我们后序的代码执行需要依赖IO的返回值,这就要用到回调了。
回调的实现有两种:
import asyncio
import time
async def sleep(x):
time.sleep(x)
return "暂停了{}秒!".format(x)
coroutine = sleep(2)
loop = asyncio.get_event_loop()
task = asyncio.ensure_future(coroutine)
loop.run_until_complete(task)
print("返回结果:{}".format(task.result()))
#返回结果:暂停了2秒!
2.通过asyncio自带的添加回调函数功能来实现。
import asyncio
import time
async def sleep(x):
time.sleep(x)
return "暂停了{}秒!".format(x)
def callback(future):
print("这里是回调函数,获取返回结果是:",future.result())
coroutine = sleep(2)
loop = asyncio.get_event_loop()
task = asyncio.ensure_future(coroutine)
task.add_done_callback(callback)
loop.run_until_complete(task)