Reputation: 353
I have problem with method open of WebSocketHandler. I wrapped it with gen.coroutine for using async call inside (get access to redis). But got another problem, any errors inside open does not catches.
Example:
@gen.coroutine
def open(self):
t = 8/0
self._connection_id = yield self._generate_connection_id()
self.write_message('...')
Method open is call inside WebSocketProtocol._run_callback :
def _run_callback(self, callback, *args, **kwargs):
try:
callback(*args, **kwargs)
except Exception:
app_log.error("Uncaught exception in %s",
self.request.path, exc_info=True)
self._abort()
This method hasn't any decorator, so method open return future and this exception doesn't handled.
So how can I use async method inside open, and handle exceptions?
Upvotes: 0
Views: 351
Reputation: 22154
As a general rule, coroutines can only correctly be called by other coroutines, so when overriding a method of a base class like WebSocketHandler.open
, unless that method is a coroutine or is documented as "may be a coroutine" or "may return a Future", it is not safe to make it a coroutine. WebSocketHandler.open
may not be a coroutine (as of Tornado 4.1).
You may spawn a coroutine from open() with IOLoop.spawn_callback
:
def open(self):
IOLoop.current().spawn_callback(self.async_open)
@gen.coroutine
def async_open(self):
#...
Within async_open
, you can handle errors as usual with try/except (spawn_callback
also logs exceptions for you as a last resort). It is also your responsibility to deal with any timing issues that may arise between async_open
and on_message
or on_close
, since those methods may be called before async_open
completes.
Upvotes: 2