今天我们来看一下 Future 这个对象。从字面意思来看有“未来,将来......”之意义。那它在Tornado 构建的体系中扮演者什么样的角色呢?我们先看一下它的源码:
以上是 Future 中比较核心的方法,为了我们能整体的把握这个类的内容明白其运行原理,我对这个类进行了整理,可以看一下我整理后对这个类中的核心代码的解释:
代码语言:javascript复制# -*- encoding: utf-8 -*-
# !/usr/bin/python
"""
@File : future_learn.py
@Time : 2020/07/25 15:40
@Author : haishiniu
@Software: PyCharm
"""
class Future(object):
def __init__(self):
self._done = False # 异步操作是否执行完成
self._result = None # 如果异步操作成功执行完成,则将结果保存到 self._result
self._exc_info = None # 如果异步操作执行过程中出现异常,则将异常信息保存到self._exc_info
self._callbacks = [] # 回调函数列表。在异步操作执行完成之后,会挨个调用这些回调函数
def running(self):
return not self._done
def done(self):
return self._done
def result(self, timeout=None):
# 如果异步操作成功执行,则返回它的结果
if self._result is not None:
return self._result
# 如果异步操作执行失败,则重新抛出异常信息
if self._exc_info is not None:
try:
raise_exc_info(self._exc_info)
except Exception as ex :
print(ex)
finally:
self = None
# 如果异步操作尚未完成,则等待它执行结束,然后返回它的结果
# 但是在 tornado 中没有实现阻塞的等待结果,
# 如果异步操作没有完成,调用该方法会引发异常
# 所以,最好是:
# if future.done():
# result = future.result()
# ...
self._check_done()
return self._result
def exception(self, timeout=None):
# 如果异步操作抛出了异常,那么就返回异常对象
if self._exc_info is not None:
return self._exc_info[1]
else:
# 如果异步操作尚未完成,则抛出异常。
# 如果异步操作成功执行,则返回None。
self._check_done()
return None
def add_done_callback(self, fn):
# 当异步操作已经执行完成时,立即调用回调函数
if self._done:
fn(self)
# 否则,添加到回调函数列表。当异步操作执行完成时,会挨个调用这些回调函数
else:
self._callbacks.append(fn)
def set_result(self, result):
# 如果该 Future 对象所绑定的异步操作,成功执行了,在异步操作中
# 应该调用 Future 对象的 set_result() 方法设置执行结果。
# 该方法会将结果保存起来,并且将 Future 对象设置为完成,最后还会挨个调用回调函数
self._result = result
self._set_done()
def set_exc_info(self, exc_info):
# 将异常信息保存到 self._exc_info 属性
self._exc_info = exc_info
try:
# 调用 _set_done() 将该Future对象标记位完成;并调用所有的回调函数
self._set_done()
except Exception as ex:
print(ex)
self._exc_info = exc_info
def _check_done(self):
# 因为在 tornado 的这个实现中,不支持阻塞等待异步操作的结果。
# 所以,当异步操作尚未完成时,会直接抛出异常。
if not self._done:
raise Exception("DummyFuture does not support blocking for results")
def _set_done(self):
self._done = True
for cb in self._callbacks:
try:
# 执行回调
cb(self)
except Exception as ex:
print(ex)
# 回调完成后 回调队列设置为 None
self._callbacks = None
在代码中我已经做了比较详尽的批注,大家可以结合代码和批注来理解这个类中的内容。 总结: 1. Future 对象是用来存储异步操作的结果的。 2. 在tornado中,Future 通常和 IOLoop.add_future()一起使用,或者由gen.coroutine 修饰的生成器函数yield它们。 3.本质上,Future就是一个"占位符"。 需要注意的是:Future是非线程安全的。
好的,本期我们就先分享到这里,若还有疑问可以给我留言进行进一步的交流,谢谢。