来自tornado.gen documentation可以有人帮我理解tornado.gen.coroutine和tornado.gen.engine之间的确切区别
最佳答案
正如gen.engine的龙卷风文档所说:
原文链接:https://www.f2er.com/python/439775.htmlThis decorator is similar to coroutine,except it does not return a
Future and the callback argument is not treated specially.
正如gen.coroutine文档所说
From the caller’s perspective,@gen.coroutine is similar to the
combination of @return_future and @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,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,tb):
try:
if runner is not None and runner.handle_exception(typ,tb):
return True
except Exception:
typ,tb = sys.exc_info()
future.set_exc_info((typ,tb))
return True
with ExceptionStackContext(handle_exception) as deactivate:
try:
result = func(*args,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对回调kwarg有一些特殊的处理,它构建/返回一个Future. @ gen.engine有一些代码,如果你试图从它返回一些东西,而不是把它放在Future中,它会特意抛出一个错误.