programming mac example async python asynchronous tornado

example - tornado python mac



Diferencia en tornado.gen.engine v/s tornado.gen.coroutine (1)

Pasando por la documentación tornado.gen alguien me puede ayudar a entender la diferencia exacta entre tornado.gen.coroutine y tornado.gen.engine


Como dice la documentación del tornado para gen.engine :

Este decorador es similar a coroutine, excepto que no devuelve un futuro y el argumento de devolución de llamada no se trata de manera especial.

Y como dice la documentación de gen.coroutine

Desde la perspectiva de la persona que llama, @ gen.coroutine es similar a la combinación de @return_future y @ gen.engine.

gen.engine es básicamente una versión más antigua, menos aerodinámica de lo que hace coroutine. Si está escribiendo un código nuevo, debe seguir los consejos de la documentación y siempre usar tornado.gen.coroutine .

Es bastante evidente si mira el código para ambas funciones (con la documentación eliminada).

motor:

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

coroutine:

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

Ambas son probablemente bastante difíciles de entender a primera vista. Pero aún así, es obvio que el código es muy similar, excepto que @gen.coroutine tiene un manejo especial del kwarg de callback de callback , y crea / devuelve un Future . @gen.engine tiene un código que específicamente arroja un error si intentas devolver algo de él, en lugar de ponerlo en el Future .