python协程——3、asyncio、await

一、定义创建协程

     在函数前面加上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

 

三、协程如何工作

      协程工作流程一般如下:

  1.  定义、创建协程对象
  2. 将协程转为task任务
  3. 定义事件循环对象容器
  4. 将task任务扔进事件循环对象中触发

代码如下:   

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。

python协程——3、asyncio、await_第1张图片

此外,

  1. yeild from后面可接可迭代对象,也可接future对象/协程对象;
  2. await 后面必须要接future对象/协程对象

我们来验证一下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的返回值,这就要用到回调了。

回调的实现有两种:

  1. 利用同步编程实现的回调,这就要求我们要能够有办法取得协程的await返回值。
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)

 

 

你可能感兴趣的:(python)