首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >tornado.gen.engine v/s tornado.gen.coroutine的差异

tornado.gen.engine v/s tornado.gen.coroutine的差异
EN

Stack Overflow用户
提问于 2014-05-06 18:34:11
回答 1查看 2.3K关注 0票数 7

通过tornado.gen 文档可以帮助我理解tornado.gen.coroutine和tornado.gen.engine之间的确切区别吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-05-06 18:48:20

正如gen.engine的龙卷风文档所述:

这个装饰器类似于coroutine,只是它不返回未来,回调参数也没有得到特殊处理。

就像gen.coroutine文档说的

从调用方的角度来看,@gen.coroutine类似于@return_future和@gen.engine的组合。

gen.engine基本上是coroutine所做的一个较老的、不那么精简的版本。如果您正在编写新代码,则应该遵循文档的建议,并始终使用tornado.gen.coroutine

很明显,如果您查看这两个函数的代码(去掉文档)。

引擎:

代码语言:javascript
复制
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

协同线:

代码语言:javascript
复制
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.coroutinecallback kwarg有一些特殊的处理,并且它构建/返回一个Future@gen.engine有一些代码,如果您试图从其中返回某个内容,而不是将其放入Future中,则会专门抛出一个错误。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23502338

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档