I have the following class:
class SessionHandler(tornado.websocket.WebSocketHandler):
@tornado.gen.coroutine
def on_message(self):
yield self.application.c.check("xxx@gmail.com")
The check() function is something like
@tornado.gen.coroutine
def check(self,id):
if id not in self.AUTH_METHOD.keys():
raise InvalidXX
InvalidXX
is a user defined exception that inherits from Exception
class.
When this exception is raised nothing is displayed to the tornado console. However when I add try/except clauses around them the exception is picked up. I don't understand why this exception isn't being propagated to the console. Other exceptions E.g. Duplicate key in MongoDB are propagated and shown to the console.
[This answer applies to Tornado 4.4 and older. As of Tornado 4.5 on_message
may be a coroutine and the code in the original question will work]
Coroutines are called differently from regular functions (i.e. they must be called with yield
). Therefore, when you are defining a method to be called by the framework, you should only use a coroutine when the docs say something like "this method may be a coroutine". WebSocketHandler.on_message
may not be a coroutine (as of Tornado 4.3).
Instead, you can use IOLoop.spawn_callback
to start an independent coroutine from your on_message
callback.
def on_message(self, msg):
IOLoop.current().spawn_callback(process_message, msg)
@gen.coroutine
def process_message(self, msg):
...
An important distinction here is that spawn_callback
detaches the coroutine from the code in WebSocketHandler
that receives messages: you may get a second on_message
call before the callback spawned in the first one has finished. Use the methods in the tornado.locks
and tornado.queues
modules to manage this concurrency. (By contrast, in RequestHandler.data_received
, which may be a coroutine, you won't get a second chunk of data until the second has been processed, and an uncaught exception will abort the connection)