通过tornado.gen 文档可以帮助我理解tornado.gen.coroutine和tornado.gen.engine之间的确切区别吗?
发布于 2014-05-06 18:48:20
正如gen.engine的龙卷风文档所述:
这个装饰器类似于coroutine,只是它不返回未来,回调参数也没有得到特殊处理。
就像gen.coroutine文档说的
从调用方的角度来看,@gen.coroutine类似于@return_future和@gen.engine的组合。
gen.engine基本上是coroutine所做的一个较老的、不那么精简的版本。如果您正在编写新代码,则应该遵循文档的建议,并始终使用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对callback kwarg有一些特殊的处理,并且它构建/返回一个Future。@gen.engine有一些代码,如果您试图从其中返回某个内容,而不是将其放入Future中,则会专门抛出一个错误。
https://stackoverflow.com/questions/23502338
复制相似问题