python 3.x asyncio中非常重要的两个类Future和Task

asyncio中非常重要的两个类Future和Task

Future:

  • 在介绍线程池中介绍了Future.
  • asyncio也有一个future,通过ensure_future()方法和create_task()方法都能够创建task,task本身就是future的子类
  • 解读asyncio包下的futures.py,这里的Future与线程池中的Future几乎是一致的.
  • future是我们的结果容器.会将结果放到future容器里面.结果容器运行完毕,会直接运行callback

Future类的方法:

源码set_result():

1                 def set_result(self, result):
2                     if self._state != _PENDING:
3                         raise InvalidStateError('{}: {!r}'.format(self._state, self))
4                     self._result = result
5                     self._state = _FINISHED
6                     # 在线程池中也会有callback
7                     self._schedule_callbacks()

 


源码_schedule_callbacks():

 1                 def _schedule_callbacks(self):
 2                     callbacks = self._callbacks[:]
 3                     if not callbacks:
 4                         return
 5 
 6                     self._callbacks[:] = []
 7                     # 循环所有回调函数
 8                     for callback in callbacks:
 9                         # 此处与线程池里面的代码不一样了,线程池中的代码是运行完了之后,直接去调用代码.
10                         # 现在这个地方因为是单线程的模式,所以说只有在一个线程里面去运行代码,所以就无法做到像单线程里面一样,运行完毕后直接运行.
11                         # 此处调用了call_soon()函数,将callback放到loop的ready队列里面去,然后loop会从ready队列里面不停的取数据然后循环.
12                         self._loop.call_soon(callback, self)

 

 

Task:

  • 解读asyncio包下的tasks.py.
  • class Task(futures.Future): Future的子类.
  • Task类设计意图是???在线程池中没有Task,而在协程里面有Task类???
  • task是future和协程直接的桥梁,通过_step()方法来理解.

源码__init__():

1                 def __init__(self, coro, *, loop=None):
2                     # ...省略代码
3 
4                     # 在初始化魔法函数中先调用一次_step()方法.
5                     self._loop.call_soon(self._step)
6                     # ...省略代码

 


源码_step():

  • 这个方法里面定义一个协程之后,在驱动协程之前,必须要对这个协程调用一次next()或者调用一次send()方法,使这个协程生效.
 1                 def _step(self, exc=None):
 2                     # ...省略代码
 3 
 4                     try:
 5                         if exc is None:
 6                             # 启动协程,线程与协程不一样,协程在最开始的时候,首先必须要经历一个启动过程.
 7                             # 线程是通过操作系统来启动的.因为协程是由程序员来调度的.所以需要自己解决协程的启动问题.
 8                             # 所以就抽象出一个task方法,这个task方法作为协程和future之间的一个桥梁.
 9                             # 这个桥梁干的第一件事就是激活协程,就是coro.send(None)语句.
10                             result = coro.send(None)
11                         else:
12                             result = coro.throw(exc)
13                     except StopIteration as exc:
14                         if self._must_cancel:
15                             self._must_cancel = False
16                             self.set_exception(futures.CancelledError())
17                         else:
18                             # 如果在运行的时候抛出StopIteration异常的话,就需要执行self.set_result(exc.value)语句
19                             # 然后将exc(exception)的value值,就是协程的return值.将协程return值设置到result里面,
20                             # 这个设置是由task来完成的.
21                             # 所以说task完成的事不光是启动协程,还将最后的StopIteration的值做了处理.
22                             # 在线程中没有StopIteration这个异常.
23                             # 所以说从设计的角度来讲,asyncio尽量的保持协程池里面的接口是一致的,为了解决这个问题就加了Task类.
24                             # 来解决协程和线程之间不一样的地方所需要解决的问题.
25                             self.set_result(exc.value)
26 
27                     # ...省略代码

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

********

posted on 2019-05-25 10:34  jaydenjune  阅读(89)  评论(0)    收藏  举报

导航