简体   繁体   English

龙卷风协程

[英]Tornado coroutine

I am trying to learn tornado coroutines, but I have error using below code. 我正在尝试学习龙卷风协程,但是使用以下代码却出错。

Traceback (most recent call last):
  File "D:\projekty\tornado\env\lib\site-packages\tornado\web.py", line 1334, in _execute
    result = yield result
  File "D:\projekty\tornado\env\lib\site-packages\tornado\gen.py", line 628, in run
    value = future.result()
  File "D:\projekty\tornado\env\lib\site-packages\tornado\concurrent.py", line 109, in result
    raise_exc_info(self._exc_info)
  File "D:\projekty\tornado\env\lib\site-packages\tornado\gen.py", line 631, in run
    yielded = self.gen.throw(*sys.exc_info())
  File "index.py", line 20, in get
    x = yield 'test'
  File "D:\projekty\tornado\env\lib\site-packages\tornado\gen.py", line 628, in run
    value = future.result()
  File "D:\projekty\tornado\env\lib\site-packages\tornado\concurrent.py", line 111, in result
    raise self._exception
BadYieldError: yielded unknown object 'test'

Code: 码:

from tornado.ioloop import IOLoop
from tornado.web import RequestHandler, Application, url
from tornado import gen

class HelloHandler(RequestHandler):
    @gen.coroutine
    def get(self):
        x = yield 'test'
        self.render('hello.html')


def make_app():
    return Application(
        [url(r"/", HelloHandler)], 
        debug = True
    )

def main():
    app = make_app()
    app.listen(8888)
    IOLoop.instance().start()

main()

As Lutz Horn pointed out, the tornado.coroutine decorator requires that you yield only Future objects or certain containers containing Future objects. 正如Lutz Horn指出的那样, tornado.coroutine装饰器仅要求您产生Future对象或某些包含Future对象的容器。 So trying to yield a str will raise an error. 因此,尝试产生str会引发错误。 I think the piece you're missing is that any place inside of a coroutine where you want to call yield something() , something must either also be a coroutine, or return a Future . 我认为您缺少的部分是协程内部任何要调用yield something()something也必须是协程,或返回Future For example, you could fix your example like this: 例如,您可以这样修改示例:

from tornado.gen import Return

class HelloHandler(RequestHandler):
    @gen.coroutine
    def get(self):
        x = yield self.do_test()
        self.render('hello.html')

    @gen.coroutine
    def do_test(self):
        raise Return('test')
        # return 'test' # Python 3.3+

Or even this (though generally you shouldn't do it this way): 甚至是这样(尽管通常您不应该这样):

class HelloHandler(RequestHandler):
    @gen.coroutine
    def get(self):
        x = yield self.do_test()
        self.render('hello.html')

    def do_test(self):
        fut = Future()
        fut.set_result("test")
        return fut

Of course, these are contrived examples; 当然,这些是人为的例子。 since we're not actually doing anything asynchronous in do_test , there's no reason to make it a coroutine. 由于我们实际上并没有在do_test执行任何异步do_test ,因此没有理由使其成为协程。 Normally you'd be doing some kind of asynchronous I/O in there. 通常,您将在其中执行某种异步I / O。 For example: 例如:

class HelloHandler(RequestHandler):
    @gen.coroutine
    def get(self):
        x = yield self.do_test()
        self.render('hello.html')

    @gen.coroutine
    def do_test(self):
        http_client = AsyncHTTPClient()
        out = yield http_client.fetch("someurl.com") # fetch is a coroutine
        raise Return(out.body)
        # return out.body # Python 3.3+

From the documentation : 从文档中

Most asynchronous functions in Tornado return a Future ; Tornado中的大多数异步函数都返回Future yielding this object returns its result. 产生此对象将返回其结果。

You can also yield a list or dict of Futures , which will be started at the same time and run in parallel; 您还可以yield a list or dict of Futures ,它们将同时启动并并行运行; a list or dict of results will be returned when they are all finished: 完成后将返回结果列表或命令:

The string "test" is not a Future . 字符串"test"不是Future Try to yield one. 尝试屈服一个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM