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) 收藏 举报
浙公网安备 33010602011771号