Python中协程异步

北京哪里医院看白癜风好 http://pf.39.net/bdfyy/xwdt/
Python中协程异步介绍异步IO:就是发起一个IO操作(如:网络请求,文件读写等),这些操作一般是比较耗时的,不用等待它结束,可以继续做其他事情,结束时会发来通知。

协程:又称为微线程,在一个线程中执行,执行函数时可以随时中断,由程序(用户)自身控制,执行效率极高,与多线程比较,没有切换线程的开销和多线程锁机制。

python中异步IO操作是通过asyncio来实现的。

为了更加详细说明asyncio,我们先从协程的最基础开始讲解。

协程基础

从语句上看,协程和生成器类似,都是包含了yield关键字,不同之处在于协程中yield关键词通常出现在=右边,可以产出值a(y=yielda)或不产出值时为None(y=yield)。调用方可以用send函数发送值给协程。

激活协程时在yield处暂停,等待调用方发送数据,下次继续在yield暂停。从根本上看,yield是流程控制的工具,可以实现协作式多任务,这也是后面讲解异步IO的基础。

最简单的协程示例

使用协程时需要预激活(next函数)后才能使用send发送值。(a=yieldb),next时会产出yield右边的值b,send时接收值的是yield左边的值a

defcoroutine_example(name):print(startcoroutine...name:,name)x=yieldname#调用next()时,产出yield右边的值后暂停;调用send()时,产出值赋给x,并往下运行print(send值:,x)coro=coroutine_example(Zarten)print(next的返回值:,next(coro))print(send的返回值:,coro.send(6))输出结果:startcoroutine...name:Zartennext的返回值:Zartensend的值:6

必须先调用next()函数预激活协程,不然send()函数无法使用。

调用next()时,产出yield右边的值后暂停不再往yield的下一行执行(一般不需要next产出值),等待send的到来,调用send()时,产出值赋给x(可对x作进一步处理),并往下运行。

协程结束时会跟生成器一样抛出StopIteration的异常给调用方,调用方可以捕获它后处理。

让协程返回值以及yieldfrom说明获取协程的返回值

当结束协程时,会返回返回值,调用方会抛出StopIteration异常,返回值就在异常对象的value属性中

defcoroutine_example(name):print(startcoroutine...name:,name)whileTrue:x=yieldname#调用next()时,产出yield右边的值后暂停;调用send()时,产出值赋给x,并往下运行ifxisNone:returnzhihuID:Zartenprint(send值:,x)coro=coroutine_example(Zarten)next(coro)print(send的返回值:,coro.send(6))try:coro.send(None)exceptStopIterationase:print(返回值:,e.value)yieldfrom说明

yieldfrom跟for循环很相似,但功能更多一些,不信你看下面代码

deffor_test():foriinrange(3):yieldiprint(list(for_test()))defyield_from_test():yieldfromrange(3)print(list(yield_from_test()))下面是输出结果:[0,1,2][0,1,2]

其实yieldfrom内部会自动捕获StopIteration异常,并把异常对象的value属性变成yieldfrom表达式的值。

yieldfromx表达式内部首先是调用iter(x),然后再调用next(),因此x是任何的可迭代对象。yieldfrom的主要功能就是打开双向通道,把最外层的调用方和最内层的子生成器连接起来。

下面代码展示:调用方发送的值在yieldfrom表达式处直接传递给子生成器,并在yieldfrom处等待子生成器的返回

defcoroutine_example(name):print(startcoroutine...name:,name)x=yieldname#调用next()时,产出yield右边的值后暂停;调用send()时,产出值赋给x,并往下运行print(send值:,x)returnzhihuID:Zartendefgrouper2():result2=yieldfromcoroutine_example(Zarten)#在此处暂停,等待子生成器的返回后继续往下执行print(result2的值:,result2)returnresult2defgrouper():result=yieldfromgrouper2()#在此处暂停,等待子生成器的返回后继续往下执行print(result的值:,result)returnresultdefmain():g=grouper()next(g)try:g.send(10)exceptStopIterationase:print(返回值:,e.value)if__name__==__main__:main()输出结果:startcoroutine...name:Zartensend的值:10result2的值:zhihuID:Zartenresult的值:zhihuID:Zarten返回值:zhihuID:Zarten

从上面也可看到yieldfrom起到一个双向通道的作用,同时子生成器也可使用yieldfrom调用另一个子生成器,一直嵌套下去直到遇到yield表达式结束链式。

yieldfrom一般用于asyncio模块做异步IO

异步IO(asyncio)

从上面我们知道了协程的基础,异步IO的asyncio库使用事件循环驱动的协程实现并发。用户可主动控制程序,在认为耗时IO处添加await(yieldfrom)。在asyncio库中,协程使用

asyncio.coroutine装饰,使用yieldfrom来驱动,在python3.5中作了如下更改:

asyncio.coroutine-async

yieldfrom-await

asyncio中几个重要概念1.事件循环

管理所有的事件,在整个程序运行过程中不断循环执行并追踪事件发生的顺序将它们放在队列中,空闲时调用相应的事件处理者来处理这些事件。

2.Future

Future对象表示尚未完成的计算,还未完成的结果

3.Task

是Future的子类,作用是在运行某个任务的同时可以并发的运行多个任务。

asyncio.Task用于实现协作式多任务的库,且Task对象不能用户手动实例化,通过下面2个函数创建:

asyncio.async()

loop.create_task()或asyncio.ensure_future()

最简单的异步IO示例run_until_



转载请注明地址:http://www.sanbaicaoasb.com/sczz/8463.html
  • 上一篇文章:
  • 下一篇文章:
  • 热点文章

    • 没有热点文章

    推荐文章

    • 没有推荐文章