正如龙卷风文档所述
gen.engine:
此装饰器与协程类似,不同之处是它不返回Future且未对回调参数进行特殊处理。
正如
gen.coroutine文档所说
从调用者的角度来看,@ gen.coroutine类似于@return_future和@ gen.engine的组合。
gen.engine基本上是协程所做的较旧的,精简的版本。如果要编写新代码,则应遵循文档的建议并始终使用
tornado.gen.coroutine。
如果您查看这两个函数的代码(去除了文档),这是很明显的。
发动机:
def engine(func): @functools.wraps(func) def wrapper(*args, **kwargs): runner = None def handle_exception(typ, value, tb): if runner is not None: return runner.handle_exception(typ, value, tb) return False with ExceptionStackContext(handle_exception) as deactivate: try: result = func(*args, **kwargs) except (Return, StopIteration) as e: result = getattr(e, 'value', None) else: if isinstance(result, types.GeneratorType): def final_callback(value): if value is not None: raise ReturnValueIgnoredError( "@gen.engine functions cannot return values: " "%r" % (value,)) assert value is None deactivate() runner = Runner(result, final_callback) runner.run() return if result is not None: raise ReturnValueIgnoredError( "@gen.engine functions cannot return values: %r" % (result,)) deactivate() # no yield, so we're done return wrapper
协程:
def coroutine(func): @functools.wraps(func) def wrapper(*args, **kwargs): runner = None future = TracebackFuture() if 'callback' in kwargs: callback = kwargs.pop('callback') IOLoop.current().add_future( future, lambda future: callback(future.result())) def handle_exception(typ, value, tb): try: if runner is not None and runner.handle_exception(typ, value, tb): return True except Exception: typ, value, tb = sys.exc_info() future.set_exc_info((typ, value, tb)) return True with ExceptionStackContext(handle_exception) as deactivate: try: result = func(*args, **kwargs) except (Return, StopIteration) as e: result = getattr(e, 'value', None) except Exception: deactivate() future.set_exc_info(sys.exc_info()) return future else: if isinstance(result, types.GeneratorType): def final_callback(value): deactivate() future.set_result(value) runner = Runner(result, final_callback) runner.run() return future deactivate() future.set_result(result) return future return wrapper乍一看,这两个都可能很难理解。但是,很明显,该代码非常相似,除了
@gen.coroutine对
callbackkwarg进行了一些特殊处理之外,它还会生成/返回a
Future。
@gen.engine如果您尝试从中返回某些内容而不是将其放入,则其中的某些代码专门抛出了错误
Future。



