2014-05-06 7 views

Antwort

4

Wie die Tornado-Dokumentation für gen.engine sagt:

Dieser Dekorateur ähnlich ist Koroutine, außer es keine Zukunft und das Callback-Argument zurückgibt ist nicht speziell behandelt.

Und als gen.coroutine Dokumentation sagt

Aus Sicht des Anrufers @ gen.coroutine zum Kombination von @return_future und @ gen.engine ähnlich ist.

gen.engine ist im Grunde eine ältere, weniger stromlinienförmige Version von was Coroutine tut. Wenn Sie neuen Code schreiben, sollten Sie den Ratschlägen der Dokumentation folgen und immer tornado.gen.coroutine verwenden.

Es ist ziemlich offensichtlich, wenn Sie den Code für beide Funktionen betrachten (mit der Dokumentation entfernt).

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 

Koroutine:

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 

Beide sind wahrscheinlich ziemlich hart auf den ersten Blick zu verstehen. Aber dennoch ist es offensichtlich, dass der Code sehr ähnlich ist, außer dass @gen.coroutine eine spezielle Handhabung des callback Kwarg hat, und es baut/gibt Future zurück. @gen.engine hat Code, der speziell einen Fehler auslöst, wenn Sie versuchen, etwas davon zurückzugeben, anstatt es in Future zu setzen.

Verwandte Themen