ASNYCIO 中task,coroutine和future

COROUTINE

Coroutine 利用async defpy3.5)去定以,或者使用生成器进行定义。

Coroutine,跟生成器差不多,用于两种不同但是相关的概念:

1:用于定义coroutinecoroutine函数,使用iscoroutinefunction()来查看是否为coroutine类型的函数

2coroutine,被coroutine类型函数调用的对象,用于能够结束的计算或者IO操作,使用iscoroutine()来查看是否为coroutine

Coroutine可以做的事:

1result = await future /yield from future, 挂起coroutine 知道future完成,然后result获得future返回的结果,或者抛出异常,该异常可被result接受(如果futurecancel掉,则会抛出一个cancellederror异常),注意task就是future,任何说的关于future的也都适用于task

(总结:也就是说coroutine可以挂起等到future或者task完成,然后获得它返回的结果继续执行下面的代码)

2result =await coroutine/yield from coroutine 挂起等待另一个coroutine产生结果,该表达式中必须是调用了另一个coroutine

3return expression:返回结果给另一个正在挂起等待它返回结果的coroutine

4raise exception

 

调用一个coroutine并不会立刻执行它的代码,被调用的coroutine不会做任何的事情除非你安排了他的执行。

有两种方法去驱动coroutine执行:一是在一个coroutine使用awaitcoroutine/yiele from coroutine 调用另一个coroutine去执行(假设调用者已经在运行)调用后,被调用者就会开始跑程序然后返回结果或者抛出异常或者再调用第三个coroutine以此类推。二是使用ensure_future()函数,或者AbstractEventLoop.create_task()函数去调用。

尝试写了一个代码如下: 

在使用被注释的那两行代码的时候,会报错,说”coroutine 'display_date' was never awaited”,也就是如果直接输入函数进行调用,会失败,因为没有启动的步骤。

FUTURE

先来看一下concurrent.future模块(http://www.cnblogs.com/skiler/p/7080179.html)

Concurrent.futures模块提供并发执行调用的高级接口,使用threads执行(使用threadPoolExecutor或者分离的processes),使用processPoolExecutor时,这个接口在抽象类Executor中定义。

Executor 对象:classconcurrent.futures.Executor

一个抽象类,提供异步调用的方法,不能被直接使用,而是通过构建子类。在爬虫中使用过的线程池和进程池的executor就是它的子类

 

concurrent.future中的FUTURE对象:

Future()封装了可调用对象的异步执行,Future的实例可以被Executor.submit()方法创建(Executor的子类)

我对future的理解就是:在Executor中提交了可调用对象(函数之后),future用于对这个提交的任务进行控制,因为工人数量有限,他有可能在执行,也有可能还等待执行,也有返回的结果,一个被声明了的future对象则就是对提交了的这一个任务的一系列操作的掌管者。

 

在例子当中,我所给的Executor的工人数量为二,在断点停留的时候并在5秒之前,可以看到:ff1这两个future对象的stateruning,也就是正在执行,f2statepending,也就是等待执行。说起这个我们再看之前的一个例子的截图,一个coroutine可以被ensure_future()去启动,在下面的代码可以看出来t1为封装为future之后的coroutine,并没有立刻执行,而是在loop.run_until_complete(t1)中才会执行。

在接触断点之后run_until_complete方法在loop中执行这个future,关于这个loop后面会讲到。

在文档中,future的方法有以下:

Cancel():尝试取消调用,状态pending可以取消返回Truerunning取消失败返回False

Cancelled():取消成功          

result(Timeout =None):拿到返回的结果,没有执行完就等待

Running():是否在运行,True/False 

exception(Timeout =None):捕获异常

Done():是否成功取消或完成running 

add_done_callback(fn):future取消或者完成后调用fn

讲完concurrent.future模块中的future,我们来看asyncio中的future,它和concurrent.future中的future基本相同。区别有以下:

         Resultexception没有timeout参数,当future没有执行完的时候调用会抛出异常。

         使用add_done_callback()注册的回调函数始终通过事件循环的call_soon_threadsafe()来调用。

         该类与concurrent.futures包中的wait()和as_completed()函数不兼容。

         该类非线程安全

         Remove_done_callback(fn):’call whendone’列表中除去所有回调函数的实例并返回除去的个数

         Set_rusult(result):

         标记future并设置它完成后的结果

         Set_exception

 

例子:Future with run_until_complete()

        

Coroutine函数负责计算(花费一秒)然后将结果存储到future当中(不使用return获取,因为coroutine不是future,使用future.result获取不了coroutine返回的结果,上面说了coroutinereturn返回给另一个挂起等待它完成的coroutine)。Run_until_complete()方法等待future的结束。

 

例子:Future with run_forever()

前一个例子可以使用future.add_done_callback()方法去写出更加清晰的控制流程

在这个例子当中,future被用于连接slow_operation() got_result(),当slow()完成后,got会被调用并打印result

 

感觉从文档来看,总结一下coroutinefuturecoroutinecoroutine之间的通信使用await,时在函数代码未执行完之间通信的,而future的话,就算不是coroutine的函数,也可以实现一个通信,而且不一定要在发出通信(set_result)者的代码结束才能发出。

看到这里有一个疑问就是启动coroutine的代码到底是哪一行,是ensure_future吗,但是执行了这行代码也没开始启动,可能要往后看才知道了。

 


TASK

Class asyncio.Task(coro,*,loop=None)

         安排coroutine的执行——在future中包装它,taskfuture的一个子类

         Task负责在一个event loop中执行coroutine对象,如果包装好的coroutine 在等待一个future,那该任务就会挂起包装好的coroutine的执行并且等待future的完成,当future完成之后,这个包装好的coroutine根据future给出的结果或者异常重新开始执行

         Eventloop 用的是一个合作调度的方法:一个Event loop只会一次只会运行一个task,其他task可以并列运行,如果在其他的线程中有别的event loop,当一个task在挂起并等待future的完成的时候,该task所在的event loop 会执行另一个新的task

         取消task 与取消future不一样,调用cancel()会向包装好的coroutine抛出一个cancelledError异常,cancelled()只会在该coroutine捕获不到cancelledError异常或者抛出cancelledError异常

         如果一个等待中的task被摧毁了,包装好的coroutine无法完成执行,将会输出Pending task destroyed

         不能直接创建task的实例,要用ensure_future()函数或者AbstractEventLoop.create_task()方法,说到这里在提一下AbstractEventLoop.run_until_complete()方法中如果接收的是一个coroutineobject的话,会自动将他包装为task

         Task也非线程安全

         类方法:

         All_tasks(loop=None):返回所有在eventloop中的task,默认下返回当前的event loop,这个是类方法,调用时写法asyncio.Task.all_tasks(loop = )

         Current_tasks(loop=None):返回目前在eventloop 中执行的task,或者none,默认同上,返回None则是因为该函数没有在该task运行的环境下调用。

         方法:

 

       Cancel():要求这个task自我取消,它安排在该loop下一次执行该task的时候向包装好的coroutine抛进一个CancelledError,然后coroutine根据给的异常执行对应代码(try/except/finally)

         不同于Future.cancel(),它不保证task会被取消,该异常会被捕获并且采取相应行动,延迟task的取消或者阻止它的取消。Task还可能给出返回值或者一个不同的异常结果

         在这个方法(cancel())被调用之后,cancelled()不会立刻返回True(除非task已经被取消掉了)task会在这个包装好的coroutine遇到CancelledError异常并终止后才被标记上取消

        

         get_stack(*,limit=None)

         print_stack()

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值