Ответ 1
@tornado.gen.coroutine
возвращает функцию return tornado.concurrent.Future
, поэтому вам не нужно вставлять ее в tornado.gen.Task
, но вы можете вызвать ее с помощью ключевого слова yield
:
@tornado.gen.coroutine
def inner():
logging.info('inner')
@tornado.gen.coroutine
def outer():
logging.info('outer')
yield inner()
Исключение в функции, украшенной таким образом, заверяется в этот объект tornado.concurrent.Future
, и его можно вернуть позже, используя его метод exception()
. В вашем случае tornado.ioloop.PeriodicCallback
вызывает ваш метод обратного вызова, после чего он просто отбрасывает возвращаемый объект tornado.concurrent.Future
вместе с исключением, содержащимся в нем. Чтобы обнаружить исключение, вы можете использовать цепной вызов:
@tornado.gen.coroutine
def inner():
raise Exception()
@tornado.gen.coroutine
def outer():
try:
yield inner()
except Exception, e:
logging.exception(e)
Но в вашем случае на самом деле проще просто поймать его сразу после метания:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import tornado.gen
import tornado.ioloop
import tornado.options
import logging
tornado.options.parse_command_line()
@tornado.gen.coroutine
def callback():
logging.info('get ready for an error...')
try:
raise Exception()
except Exception, e:
logging.exception(e)
main_loop = tornado.ioloop.IOLoop.instance()
scheduler = tornado.ioloop.PeriodicCallback(callback, 1000, io_loop = main_loop)
scheduler.start()
main_loop.start()
@gen.engine
не возвращает функцию a tornado.concurrent.Future
, поэтому исключения не завертываются.