example - tornado python mac
En Tornado, ¿cómo puedo ver Exceptions rasied en una corrutina llamada por PeriodicCallback? (2)
No entiendo exactamente por qué, pero cambiar @gen.coroutine
a @gen.engine
permite que la excepción se @gen.engine
correctamente. Todavía funciona de manera asíncrona también.
Escribí un programa que tiene una coroutine llamada periódicamente desde el ioloop
principal de esta manera:
from tornado import ioloop, web, gen, log
tornado.log.enable_pretty_printing()
import logging; logging.basicConfig()
@gen.coroutine
def callback():
print ''get ready for an error...''
raise Exception()
result = yield gen.Task(my_async_func)
l = ioloop.IOLoop.instance()
cb = ioloop.PeriodicCallback(callback, 1000, io_loop=l)
cb.start
l.start()
El resultado que obtengo es simplemente:
$ python2 app.py
get ready for an error...
get ready for an error...
get ready for an error...
get ready for an error...
¡La raise Exception()
se ignora silenciosamente! Si cambio la devolución de llamada para ser solo
def callback():
print ''get ready for an error...''
raise Exception()
Obtengo un seguimiento de pila completo como espero (y necesito). ¿Cómo puedo obtener ese rastro de pila mientras uso coroutine?
@tornado.gen.coroutine
hace que la función devuelva el objeto tornado.concurrent.Future
para que no tenga que envolverlo en tornado.gen.Task
pero puede llamarlo usando la palabra clave yield
:
@tornado.gen.coroutine
def inner():
logging.info(''inner'')
@tornado.gen.coroutine
def outer():
logging.info(''outer'')
yield inner()
Una excepción en la función decorada de esta manera se tornado.concurrent.Future
este objeto tornado.concurrent.Future
y se puede devolver más tarde utilizando su método exception()
. En su caso, tornado.ioloop.PeriodicCallback
llama a su método de devolución de llamada y, después de eso, está simplemente tornado.concurrent.Future
objeto tornado.concurrent.Future
devuelto junto con la excepción que contenía. Para detectar una excepción, puede usar la llamada en cadena:
@tornado.gen.coroutine
def inner():
raise Exception()
@tornado.gen.coroutine
def outer():
try:
yield inner()
except Exception, e:
logging.exception(e)
Pero en su caso, en realidad es más fácil simplemente atraparlo justo después de tirar:
#!/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
no hace que la función devuelva un tornado.concurrent.Future
por lo que las excepciones no se envuelven.