tornado: No way to catch exceptions when calling coroutine from gen.Task
from tornado import gen
from tornado.ioloop import IOLoop
@gen.coroutine
def throw():
10/0 # Exception here
return 'hello'
@gen.coroutine
def test():
print "i'm ok"
res = yield gen.Task(throw)
print "here too" # it is never executed
test()
IOLoop.instance().start()
There must be a way to catch exceptions.
About this issue
- Original URL
- State: closed
- Created 11 years ago
- Comments: 15 (9 by maintainers)
@kanski you could catch the exception like so:
This prints:
A few corrections to your code, by the way. Since all coroutines return Futures, you can omit gen.Task and have the same outcome:
Also, if you ever put a
yieldstatement inthrow()then thereturn 'hello'will no longer be valid: you’ll get aSyntaxError: 'return' with argument inside generatorin Pythons older than 3.3. Better to useraise gen.Return('hello').So, the real question you’re asking is, I think, what happened to the exception? and the answer is, it’s wrapped in the
Futurereturned bytest(). If you do not add a try / except intest, you can do this to catch the exception instead:If you run this code you’ll get a lengthy traceback ending in
ZeroDivisionError.I agree that this is a confusing consequence of using
gen.coroutinein a command-line application like the one you’re writing. If you were using coroutines in RequestHandlers for a web application, Tornado would log or display the error.The method IOLoop.run_sync exists to help with this situation:
IOLoop.instance().run_sync(test)is equivalent to the block above with future.add_done_callback.