web-dev-qa-db-ja.com

トルネードコルーチン

竜巻コルーチンを学習しようとしていますが、以下のコードを使用するとエラーが発生します。

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'

コード:

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()
13
klis87

Lutz Hornが指摘したように、_tornado.coroutine_デコレータでは、FutureオブジェクトまたはFutureオブジェクトを含む特定のコンテナのみを生成する必要があります。したがって、strを生成しようとすると、エラーが発生します。不足しているのは、コルーチン内でyield something()somethingを呼び出したい場所は、コルーチンであるか、Futureを返す必要があるということです。たとえば、次のように例を修正できます。

_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+
_

またはこれでさえ(一般的にあなたはそれをこのようにすべきではありませんが):

_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
_

もちろん、これらは不自然な例です。 _do_test_では実際には非同期を実行していないため、コルーチンにする理由はありません。通常、そこで何らかの非同期I/Oを実行します。例えば:

_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+
_
30
dano

ドキュメントから

Tornadoのほとんどの非同期関数は、Future;を返します。このオブジェクトを生成すると、その結果が返されます。

yield a list or dict of Futures、これは同時に開始され、並行して実行されます。結果のリストまたはdictは、すべて終了したときに返されます。

文字列"test"Futureではありません。 1つを譲ってみてください。

3
user1907906