ラッパーには将来の復帰がありません - これがなければ、非同期呼び出しがあるとioloopは続行しません。私はそれを簡単にするためにデコレータから()
を削除した、あなたが述べたかもしれませんが、いくつかのは、非同期呼び出し
@handle_exceptions
@gen.coroutine
def run_task(job_id):
logger.info('executing job {}'.format(job_id))
yield gen.sleep(1)
raise Exception('blah')
を追加してみましょう。ネストする必要はありません。
def handle_exceptions(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
future = fn(*args, **kwargs)
future.add_done_callback(handle_callback)
return future # <<< we need this
return wrapper
次に、ハンドラのコールバックがすぐに再レイズます例外をFuture.result()
を呼んでいる:だからデコレータは次のようになります。私は、それ自体でロギングに関するあらゆる情報を提供していない質問ので
import logging
from functools import wraps, partial
from tornado import gen, ioloop
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def handle_callback(result):
exc_info = result.exc_info()
if exc_info:
logger.error('EXCEPTION %s', exc_info)
def handle_exceptions(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
future = fn(*args, **kwargs)
future.add_done_callback(handle_callback)
return future
return wrapper
@handle_exceptions
@gen.coroutine
def run_task(job_id):
logger.info('executing job {}'.format(job_id))
yield gen.sleep(1)
raise Exception('blah')
ioloop.IOLoop.instance().run_sync(partial(run_task, 123))
:
def handle_callback(result):
exc_info = result.exc_info()
if exc_info:
logger.error('EXCEPTION %s', exc_info)
簡単な例で一緒にこれを置く:だから、最初の場所で例外があるかどうかを確認する方が良いでしょうレベルを変更して標準を使用しました。 コード出力:
INFO:root:executing job 123
ERROR:root:EXCEPTION (<type 'exceptions.Exception'>, Exception('blah',), <traceback object at 0x7f807df07dd0>)
Traceback (most recent call last):
File "test.py", line 31, in <module>
ioloop.IOLoop.instance().run_sync(partial(run_task, 123))
File "/tmp/so/lib/python2.7/site-packages/tornado/ioloop.py", line 458, in run_sync
return future_cell[0].result()
File "/tmp/so/lib/python2.7/site-packages/tornado/concurrent.py", line 238, in result
raise_exc_info(self._exc_info)
File "/tmp/so/lib/python2.7/site-packages/tornado/gen.py", line 1069, in run
yielded = self.gen.send(value)
File "test.py", line 28, in run_task
raise Exception('blah')
Exception: blah
他の問題がある場合は、私はそれは、ロギングの設定/セットアップに近い関連推測。
しかし私は、(呼び出し元の) 'yield'を(呼び出し先の)' gen.Return'と組み合わせて使うことにしました。そして、 'except try'ブロックで例外を処理することができます。通常の 'sync'実行と同じくらい良いでしょうか?参考用 - > https://gist.github.com/pranav93/3c34d6cfc2b5d8956625e4cd66bdfa34 – pnv