2013-05-25 6 views
11

Ich schrieb ein Programm, das eine Koroutine regelmäßig vom Haupt ioloop wie folgt aufgerufen hat:Wie kann ich in Tornado Ausnahmen in einer von PeriodicCallback aufgerufenen Coroutine sehen?

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

Der Ausgang I ist einfach zu bekommen:

$ python2 app.py 
get ready for an error... 
get ready for an error... 
get ready for an error... 
get ready for an error... 

Die raise Exception() ignoriert still! Wenn ich den Callback so ändere, dass er nur

ist, bekomme ich einen vollen Stack-Trace wie ich es erwarte (und brauche). Wie kann ich diese Stapelverfolgung während der Verwendung der Coroutine erhalten?

Antwort

4

Ich verstehe nicht genau, warum, aber die Änderung @gen.coroutine zu @gen.engine ermöglicht die Ausnahme, um richtig Blase. Es funktioniert auch noch asynchron.

+0

Um Ausnahmen zu behandeln gen.coroutine fängt "Exception" -Fehler. gen.engine mach das nicht. Siehe http://stackoverflow.com/a/23502625/1066801 – M07

7

@tornado.gen.coroutine macht Funktion Rückkehr tornado.concurrent.Future Objekt, so dass Sie es in tornado.gen.Task nicht wickeln müssen, aber Sie können es yield Schlüsselwort nennen:

in diesem tornado.concurrent.Future Objekt
@tornado.gen.coroutine 
def inner(): 
    logging.info('inner') 

@tornado.gen.coroutine 
def outer(): 
    logging.info('outer') 
    yield inner() 

Eine Ausnahme in der Funktion auf diese Weise eingerichtet gewickelt und es kann später unter Verwendung seiner exception() Methode zurückgegeben werden. In Ihrem Fall tornado.ioloop.PeriodicCallback ruft Ihre Callback-Methode und danach ist es nur weg geworfen tornado.concurrent.Future Objekt zusammen mit Ausnahme enthalten. Zur Erkennung Ausnahme können Sie Kette calling verwenden:

@tornado.gen.coroutine 
def inner(): 
    raise Exception() 

@tornado.gen.coroutine 
def outer(): 
    try: 
     yield inner() 
    except Exception, e: 
     logging.exception(e) 

Aber in Ihrem Fall ist es tatsächlich einfacher, nur um es zu fangen gerade nach dem Werfen:

#!/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 nicht Funktion machen zurückgeben eine tornado.concurrent.Future so Ausnahmen aren‘ t eingewickelt.

Verwandte Themen