@gen.coroutine
Tornado 3 の新機能です。http://www.tornadoweb.org/en/stable/releases/v3.0.0.htmlから:
新しいデコレーター @gen.coroutine は、@gen.engine の代替として利用できます。これは自動的に Future を返し、コールバックを呼び出す代わりに関数内で raise gen.Return(value) を使用して値を返します (または Python 3.3 では単に値を返します)。
ドキュメントから( http://www.tornadoweb.org/en/stable/gen.html#tornado.gen.coroutine ):
このデコレーターを持つ関数は Future を返します。さらに、コールバック キーワード引数を使用して呼び出すこともできます。これは、解決時にフューチャの結果とともに呼び出されます。コルーチンが失敗した場合、コールバックは実行されず、周囲の StackContext に例外が発生します。コールバック引数は、装飾された関数内では表示されません。デコレータ自体によって処理されます。
したがって、コールバックについて心配する必要はなく、関数を にラップする必要もありませんtornado.gen.Task()
。連鎖は簡単になりました:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import logging
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.gen
from tornado.options import define, options
define("port", default=8000, help="run on the given port", type=int)
class MainHandler(tornado.web.RequestHandler):
@tornado.gen.coroutine
def outer(self):
logging.info('outer starts')
yield self.inner()
yield self.inner()
logging.info('outer ends')
raise tornado.gen.Return('hello')
@tornado.gen.coroutine
def inner(self):
logging.info('inner runs')
@tornado.web.asynchronous
@tornado.gen.coroutine
def get(self):
res = yield self.outer()
self.write(res)
if __name__ == "__main__":
tornado.options.parse_command_line()
app = tornado.web.Application(handlers=[(r"/", MainHandler)])
http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(options.port)
tornado.ioloop.IOLoop.instance().start()
出力:
$ python test.py
[I 130529 03:18:35 test:21] outer starts
[I 130529 03:18:35 test:29] inner runs
[I 130529 03:18:35 test:29] inner runs
[I 130529 03:18:35 test:24] outer ends
[I 130529 03:18:35 web:1514] 200 GET / (127.0.0.1) 1.48ms
Python 3.3 からは、 を使用する必要はありません。gen.Result()
シンプルreturn
で済みます。古いバージョンでは、'return' with argument inside generator
エラーが発生します。
また、確認してください:https://github.com/facebook/tornado/issues/759
アップデート:
Tornado 2.x に関しては、コールバックを非表示にする簡単な方法はないと思います。ドキュメントの状態:
ほとんどの場合、engine で装飾された関数は、コールバック引数を取り、終了時にその結果で呼び出す必要があります。注目すべき例外の 1 つは、コールバック引数の代わりに self.finish() を使用する RequestHandler の get/post/etc メソッドです。
ですから、それらは避けられないのではないかと心配しています。例:
class MainHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
@tornado.gen.engine
def get(self):
res = yield tornado.gen.Task(self.outer)
self.write(res)
self.finish()
def inner(self, callback):
logging.info('inner runs')
callback()
@tornado.gen.engine
def outer(self, callback):
logging.info('outer starts')
yield tornado.gen.Task(self.inner)
yield tornado.gen.Task(self.inner)
logging.info('outer ends')
callback("hello")